/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 picoSqlNet - picoSQL client library

 Copyright (C) Picosoft s.r.l. 1994-2002

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
static char rcsid[] = "$Id$";

# ifdef WIN32
# include <windows.h>
# include <sql.h>
# include <sqlext.h>
static char User[9 + 1];
static char Password[9 + 1];
extern HINSTANCE ghInstance;
# else
extern "C" {
# include "sqltype.h"
}
# endif
# ifdef MSDOS
# define strlen lstrlen
# define strcpy lstrcpy
# define strncpy lstrcpyn
# else
# include <string.h>
# endif
# include <stdio.h>
# include "sqlhndls.h"
# include "dberror.h"
# include "envirini.h"

# define MAXDBDIR 128
# define DRIVER_VER "1.00.0399"

# define DRIVER_NAME "PICOSQLN.DLL"
# define SERVER_NAME "PICOSQLN" 
# define DBMS_NAME "picoSQL"
# define DBMS_VER   "1.00.0000" 

# define CONVSUPP (SQL_CVT_CHAR|SQL_CVT_DOUBLE)
/*
# define CONVSUPP (SQL_CVT_CHAR    | SQL_CVT_SMALLINT | SQL_CVT_INTEGER | \
                   SQL_CVT_DECIMAL | SQL_CVT_FLOAT    | SQL_CVT_DOUBLE  | \
                   SQL_CVT_REAL    | SQL_CVT_NUMERIC  | SQL_CVT_TIMESTAMP)
*/

# define DATAERROR() \
       AddError (0, myHdbc, 0, "22003", 0, "Numeric value out of range"), \
       Return = SQL_ERROR
       
# define DATATRUNCATED() \
       AddError (0, myHdbc, 0, "01004", 0, "Data truncated"), \
       Return = SQL_SUCCESS_WITH_INFO

# define STR(s) \
   len = strlen(s); \
   if (rgbInfoValue != (PTR) 0) { \
      if (cbInfoValueMax > len) \
         strcpy((char *)rgbInfoValue,s); \
      else { \
         if (cbInfoValueMax > 0) { \
            strncpy((char *)rgbInfoValue,s,cbInfoValueMax); \
            ((char *)rgbInfoValue)[cbInfoValueMax - 1] = 0; \
         } \
         DATATRUNCATED(); \
      } \
   } \
   if (pcbInfoValue != (SWORD FAR *) 0) \
      *pcbInfoValue = len

# define NUM(type,num)\
   if (rgbInfoValue != (PTR) 0) \
      if (cbInfoValueMax >= sizeof(type)) \
         *(type *) rgbInfoValue = num; \
      else \
         DATAERROR(); \
   if (pcbInfoValue != (SWORD FAR *) 0) \
      *pcbInfoValue = sizeof(type)

extern "C" { 

RETCODE SQL_API SQLGetInfo(
    HDBC    hdbc,
    UWORD   fInfoType,
    PTR rgbInfoValue,
    SWORD   cbInfoValueMax,
    SWORD FAR *pcbInfoValue)
{
    RETCODE Return = SQL_SUCCESS;
    EnvirIni *odbcEnv = 0;
    int len;
    ClntHdbc *myHdbc = (ClntHdbc *) hdbc;
    

   if (!myHdbc || !myHdbc->IsA(ClntHdbc::Class)) 
      return SQL_INVALID_HANDLE;

    switch (fInfoType) {
    case SQL_ACTIVE_CONNECTIONS:
    case SQL_ACTIVE_STATEMENTS:
       NUM(SWORD,0);
       break;
    case SQL_DATA_SOURCE_NAME:
       STR(myHdbc->name.gets());
       break;
    case SQL_DRIVER_HENV:
       // Implemented by the Driver Manager alone
       break;
    case SQL_DRIVER_HDBC:
       // Implemented by the Driver Manager alone
       break;
    case SQL_DRIVER_HSTMT:
       // Implemented by the Driver Manager alone
       break;
    case SQL_DRIVER_NAME:
       STR(DRIVER_NAME);
       break;
    case SQL_DRIVER_VER:
       STR(DRIVER_VER);
       break;
    case SQL_FETCH_DIRECTION:
       NUM(SDWORD, SQL_FD_FETCH_NEXT |
                   SQL_FD_FETCH_FIRST |
                   SQL_FD_FETCH_LAST |
                   SQL_FD_FETCH_PRIOR /*|
                   SQL_FD_FETCH_ABSOLUTE |
                   SQL_FD_FETCH_RELATIVE |
                   SQL_FD_FETCH_RESUME |
                   SQL_FD_FETCH_BOOKMARK */);
       break;
    case SQL_ODBC_API_CONFORMANCE:
       NUM(SWORD,SQL_OAC_LEVEL2);
       break;
    case SQL_ODBC_SAG_CLI_CONFORMANCE:
       NUM(SWORD,SQL_OSCC_NOT_COMPLIANT);
       break;
    case SQL_ODBC_SQL_CONFORMANCE:
       NUM(SWORD,SQL_OSC_CORE);
       break;
    case SQL_ODBC_SQL_OPT_IEF:
       STR("N");
       break;
    case SQL_ODBC_VER:
       // Implemented by the Driver Manager alone
       break;
    case SQL_PROCEDURES:
       STR("N");
       break;
    case SQL_ROW_UPDATES:
       STR("N");
       break;
    case SQL_SEARCH_PATTERN_ESCAPE:
       STR("\\");
       break;
    case SQL_SERVER_NAME:
       STR(SERVER_NAME);
       break;
    case SQL_DATABASE_NAME:
       STR("");
       break;
    case SQL_DBMS_NAME:
       STR(DBMS_NAME);
       break;
    case SQL_DBMS_VER:
       STR(DBMS_VER);
       break;
    case SQL_ACCESSIBLE_TABLES:
       STR("Y");
       break; 
    case SQL_ACCESSIBLE_PROCEDURES:
       STR("N");
       break;
    case SQL_CONCAT_NULL_BEHAVIOR:
       NUM(SWORD,SQL_CB_NON_NULL);
       break;
    case SQL_CURSOR_COMMIT_BEHAVIOR:
    case SQL_CURSOR_ROLLBACK_BEHAVIOR:
       NUM(SWORD,SQL_CB_PRESERVE);
       break;
    case SQL_DATA_SOURCE_READ_ONLY:
       STR("N");
       break;
    case SQL_DEFAULT_TXN_ISOLATION:
       NUM(SDWORD,SQL_TXN_READ_UNCOMMITTED);
       break;
    case SQL_EXPRESSIONS_IN_ORDERBY:
       STR("N");
       break;
    case SQL_IDENTIFIER_CASE:
       NUM(SWORD,SQL_IC_UPPER);
       break;
    case SQL_IDENTIFIER_QUOTE_CHAR:
       STR(" ");
       break;
    case SQL_MAX_COLUMN_NAME_LEN:
       NUM(SWORD,30);
       break;
    case SQL_MAX_CURSOR_NAME_LEN:
    case SQL_MAX_OWNER_NAME_LEN:
    case SQL_MAX_PROCEDURE_NAME_LEN:
    case SQL_MAX_QUALIFIER_NAME_LEN:
       NUM(SWORD,30);
       break;
    case SQL_MAX_TABLE_NAME_LEN:
       NUM(SWORD,30);
       break;
    case SQL_MULT_RESULT_SETS:
       STR("N");
       break;
    case SQL_MULTIPLE_ACTIVE_TXN:
       STR("N");
       break;
    case SQL_OUTER_JOINS:
       STR("Y");
       break;  
    case SQL_OWNER_TERM:
       STR("");
       break;
    case SQL_PROCEDURE_TERM:
       STR("");
       break;
    case SQL_QUALIFIER_NAME_SEPARATOR:
       STR("");
       break;
    case SQL_QUALIFIER_TERM:
       STR("");
       break;
    case SQL_SCROLL_CONCURRENCY:
       NUM(SDWORD,SQL_SCCO_READ_ONLY|SQL_SCCO_LOCK);
       break;
    case SQL_SCROLL_OPTIONS:
       NUM(SDWORD,SQL_SO_FORWARD_ONLY);
       break;
    case SQL_TABLE_TERM:
       STR("TABLE");
       break;
    case SQL_TXN_CAPABLE:
       NUM(SWORD,SQL_TC_DDL_IGNORE);
       break;
    case SQL_TXN_ISOLATION_OPTION:
       NUM(SDWORD,SQL_TXN_READ_UNCOMMITTED);
       break; 
    case SQL_USER_NAME:
       STR("");
       break; 
    case SQL_CONVERT_FUNCTIONS:
       NUM(SDWORD,SQL_FN_CVT_CONVERT);
       break;
    case SQL_NUMERIC_FUNCTIONS:
       NUM(SDWORD,SQL_FN_NUM_ABS|SQL_FN_NUM_ROUND);
/*
                |
               SQL_FN_NUM_ACOS |
               SQL_FN_NUM_ASIN |
               SQL_FN_NUM_ATAN |
               SQL_FN_NUM_ATAN2 |
               SQL_FN_NUM_CEILING |
               SQL_FN_NUM_COS |
               SQL_FN_NUM_COT |
               SQL_FN_NUM_EXP |
               SQL_FN_NUM_FLOOR |
               SQL_FN_NUM_LOG |
               SQL_FN_NUM_MOD |
               SQL_FN_NUM_RAND |
               SQL_FN_NUM_PI |
               SQL_FN_NUM_SIGN |
               SQL_FN_NUM_SIN |
               SQL_FN_NUM_SQRT |
               SQL_FN_NUM_TAN |
*/     
       break;
    case SQL_STRING_FUNCTIONS:
       NUM(SDWORD,SQL_FN_STR_CONCAT|
                  SQL_FN_STR_LTRIM|
                  SQL_FN_STR_LENGTH|
                  SQL_FN_STR_LCASE |
                  SQL_FN_STR_RTRIM |
                  SQL_FN_STR_SUBSTRING |
                  SQL_FN_STR_UCASE);
/*
               SQL_FN_STR_ASCII |
               SQL_FN_STR_CHAR |
               SQL_FN_STR_INSERT |
               SQL_FN_STR_LEFT |
               SQL_FN_STR_LOCATE |
               SQL_FN_STR_REPEAT |
               SQL_FN_STR_REPLACE |
               SQL_FN_STR_RIGHT |;
*/     
       break;
    case SQL_SYSTEM_FUNCTIONS:
       NUM(SDWORD,0);
       break;
    case SQL_TIMEDATE_FUNCTIONS:
       NUM(SDWORD,0);
/*
               SQL_FN_TD_NOW |
*/     
       break;
    case SQL_CONVERT_BIGINT:
       NUM(SDWORD,0);
       break;
    case SQL_CONVERT_BINARY:
       NUM(SDWORD,0);
       break;
    case SQL_CONVERT_BIT:
       NUM(SDWORD,0);
       break;
    case SQL_CONVERT_CHAR:
       NUM(SDWORD,CONVSUPP);
       break;
    case SQL_CONVERT_DATE:
       NUM(SDWORD,0);
       break;
    case SQL_CONVERT_DECIMAL:
       NUM(SDWORD,CONVSUPP);
       break;
    case SQL_CONVERT_DOUBLE:
       NUM(SDWORD,CONVSUPP);
       break;
    case SQL_CONVERT_FLOAT:
       NUM(SDWORD,CONVSUPP);
       break;
    case SQL_CONVERT_INTEGER:
       NUM(SDWORD,CONVSUPP);
       break; 
    case SQL_CONVERT_LONGVARBINARY:
       NUM(SDWORD,0);
       break;
    case SQL_CONVERT_LONGVARCHAR:
       NUM(SDWORD,0);
       break;
    case SQL_CONVERT_NUMERIC:
       NUM(SDWORD,CONVSUPP);
       break;
    case SQL_CONVERT_REAL:
       NUM(SDWORD,CONVSUPP);
       break;
    case SQL_CONVERT_SMALLINT:
       NUM(SDWORD,CONVSUPP);
       break;
    case SQL_CONVERT_TIME:
       NUM(SDWORD,0);
       break;
    case SQL_CONVERT_TIMESTAMP:
       NUM(SDWORD,0);
       break; 
    case SQL_CONVERT_TINYINT:
       NUM(SDWORD,0);
       break; 
    case SQL_CONVERT_VARBINARY:
       NUM(SDWORD,0);
       break;
    case SQL_CONVERT_VARCHAR:
       NUM(SDWORD,0);
       break;
    case SQL_CORRELATION_NAME: // 74
       NUM(SWORD,SQL_CN_ANY);
       break;
    case SQL_NON_NULLABLE_COLUMNS: // 75
       NUM(SWORD,SQL_NNC_NULL);
       break;
    case SQL_DRIVER_HLIB: // 76
       // Implemented by the Driver Manager alone
       break;
    case SQL_DRIVER_ODBC_VER: // 77
       STR("02.10");
       break;
    case SQL_LOCK_TYPES: // 78 NS
       NUM(SDWORD,SQL_LCK_EXCLUSIVE|SQL_LCK_UNLOCK);
       break;
    case SQL_POS_OPERATIONS: // 79 NS
       NUM(SDWORD,0L);
       break;
    case SQL_POSITIONED_STATEMENTS: // 80 NS
       NUM(SDWORD,0L);
       break;
    case SQL_GETDATA_EXTENSIONS: // 81
       NUM(SDWORD,SQL_GD_ANY_COLUMN|
                  SQL_GD_ANY_ORDER| 
                  SQL_GD_BOUND);
       break;
    case SQL_BOOKMARK_PERSISTENCE: // 82 NS
       NUM(SDWORD,0L);
       break;
    case SQL_STATIC_SENSITIVITY: // 83 NS
       NUM(SDWORD,0L);
       break;
    case SQL_FILE_USAGE: // 84
       NUM(SWORD,SQL_FILE_NOT_SUPPORTED);
       break;
    case SQL_NULL_COLLATION: // 85
       NUM(SWORD,SQL_NC_HIGH);
       break;
    case SQL_ALTER_TABLE: // 86 NS
       NUM(SDWORD,0L);
       break;
    case SQL_COLUMN_ALIAS: // 87
       STR("Y");
       break;
    case SQL_GROUP_BY: // 88
       NUM(SWORD,SQL_GB_GROUP_BY_CONTAINS_SELECT);
       break;
    case SQL_KEYWORDS: // 89
       STR("");
       break;
    case SQL_ORDER_BY_COLUMNS_IN_SELECT: // 90
       STR("N");
       break;
    case SQL_OWNER_USAGE: // 91
       NUM(SDWORD,0L);
       break;
    case SQL_QUALIFIER_USAGE: // 92
       NUM(SDWORD,0L);
       break;
    case SQL_QUOTED_IDENTIFIER_CASE: // 93 NS
       NUM(UWORD,SQL_IC_UPPER);
       break;
    case SQL_SPECIAL_CHARACTERS: // 94
       STR("");
       break;
    case SQL_SUBQUERIES: // 95 NS
       NUM(SDWORD,SQL_SQ_EXISTS);
       break;
    case SQL_UNION: // 96
       NUM(SDWORD,0L);
       break;
    case SQL_MAX_COLUMNS_IN_GROUP_BY: // 97
       NUM(SWORD,0L);
       break;
    case SQL_MAX_COLUMNS_IN_INDEX: // 98
       NUM(SWORD,0L);
       break;
    case SQL_MAX_COLUMNS_IN_ORDER_BY: // 99
       NUM(SWORD,0L);
       break;
    case SQL_MAX_COLUMNS_IN_SELECT: // 100
       NUM(SWORD,0L);
       break;
    case SQL_MAX_COLUMNS_IN_TABLE: // 101
       NUM(SWORD,0L);
       break;
    case SQL_MAX_INDEX_SIZE: // 102
       NUM(SDWORD,250L);
       break;
    case SQL_MAX_ROW_SIZE_INCLUDES_LONG: // 103
       STR("Y");
       break;
    case SQL_MAX_ROW_SIZE: // 104 
       NUM(SDWORD,0x7FFFL);
       break;
    case SQL_MAX_STATEMENT_LEN: //  105 
       NUM(SDWORD,0L);
       break;
    case SQL_MAX_TABLES_IN_SELECT: // 106 
       NUM(SWORD,0);
       break;
    case SQL_MAX_USER_NAME_LEN: // 107 
       NUM(SWORD,30);
       break;
    case SQL_MAX_CHAR_LITERAL_LEN: //  108 
       NUM(SDWORD,0x7FFFL);
       break;
    case SQL_TIMEDATE_ADD_INTERVALS: // 109 
       NUM(SDWORD,0L);
       break;
    case SQL_TIMEDATE_DIFF_INTERVALS: // 110 
       NUM(SDWORD,0L);
       break;
    case SQL_NEED_LONG_DATA_LEN: //  111
       STR("N");
       break;
    case SQL_MAX_BINARY_LITERAL_LEN: // 112
       NUM(SDWORD,0L);
       break;
    case SQL_LIKE_ESCAPE_CLAUSE: // 113
       STR("N");
       break;
    case SQL_QUALIFIER_LOCATION: // 114 NS
       NUM(SWORD,0L);
       break;
    case SQL_OJ_CAPABILITIES:
      if (cbInfoValueMax >= sizeof(SDWORD))  // Particolarita' per MSQUERY
         NUM(SDWORD,SQL_OJ_LEFT|SQL_OJ_RIGHT|SQL_OJ_NESTED|SQL_OJ_INNER);
      else if (cbInfoValueMax >= sizeof(SWORD))
         NUM(SWORD,SQL_OJ_LEFT|SQL_OJ_RIGHT|SQL_OJ_NESTED|SQL_OJ_INNER);
       break;
    case SQL_CREATE_VIEW:
       NUM(SWORD,SQL_CV_CREATE_VIEW|SQL_CV_CHECK_OPTION);
       break;
    case 65000: // SQL_CORRELATION_NAME
       if (rgbInfoValue != (PTR) 0)
          *(SWORD *)rgbInfoValue = 2; // SQL_CN_ANY
       if (pcbInfoValue != (SWORD FAR *) 0)
          *pcbInfoValue = sizeof(SWORD);
       break;
    case 65001:  // SQL_NON_NULLABLE_COLUMNS
       if (rgbInfoValue != (PTR) 0)
          *(SWORD *)rgbInfoValue = 0;
       if (pcbInfoValue != (SWORD FAR *) 0)
          *pcbInfoValue = sizeof(SWORD);
       break;
    default:
       AddError (0, myHdbc, 0, "S1096", 0, "Information type out of range");
       Return = SQL_ERROR;
       break;
    }

    return Return;
}

RETCODE SQL_API SQLGetTypeInfo(
    HSTMT   hstmt,
    SWORD   fSqlType)
{
   RETCODE Return = SQL_ERROR;
   ClntHstmt *myHstmt = (ClntHstmt *) hstmt;
   void *argv[3];

   if (!myHstmt || !myHstmt->IsA(ClntHstmt::Class))
      return SQL_INVALID_HANDLE;

   DelError(0, 0, myHstmt);
   argv[0] = &Return;
   argv[1] = (void *) &myHstmt->srvHstmt;
   argv[2] = (void *) &fSqlType;
   Exception *ex = Exception_new();
   if (!Invoke_invoke (myHstmt->hdbc->call, ex, "SQLGetTypeInfo", argv)) {
      char stat[6];
      sprintf (stat,"08%03d", ex->code);
      AddError (0, 0, myHstmt, stat, ex->code, ex->description);
      Exception_log(ex);
   }
   Exception_delete (ex);
   return Return;
}

RETCODE SQL_API Dummy()
{
   return SQL_SUCCESS;
}

};
