LCOV - code coverage report
Current view: top level - src/odbc - info.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 47 563 8.3 %
Date: 2026-11-07 23:58:45 Functions: 1 2 50.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001  Brian Bruns
       3             :  * Copyright (C) 2002-2012  Frediano Ziglio
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : /**
      22             :  * \file
      23             :  * SQLGetInfo and SQLGetFunctions implementation
      24             :  */
      25             : 
      26             : #include <config.h>
      27             : 
      28             : #include <stdio.h>
      29             : 
      30             : #if HAVE_STRING_H
      31             : #include <string.h>
      32             : #endif /* HAVE_STRING_H */
      33             : 
      34             : #include <freetds/utils.h>
      35             : #include <freetds/odbc.h>
      36             : #include <odbcss.h>
      37             : 
      38             : /**
      39             :  * Log a useful message about unimplemented options
      40             :  * Defying belief, Microsoft defines mutually exclusive options that
      41             :  * some ODBC implementations #define as duplicate values (meaning, of course,
      42             :  * that they couldn't be implemented in the same function because they're
      43             :  * indistinguishable.
      44             :  *
      45             :  * Those duplicates are commented out below.
      46             :  */
      47             : static void
      48           0 : odbc_log_unimplemented_type(const char function_name[], int fType)
      49             : {
      50             :         const char *name, *category;
      51             : 
      52           0 :         switch (fType) {
      53             : #ifdef SQL_ALTER_SCHEMA
      54             :         case SQL_ALTER_SCHEMA:
      55             :                 name = "SQL_ALTER_SCHEMA";
      56             :                 category = "Supported SQL";
      57             :                 break;
      58             : #endif
      59             : #ifdef SQL_ANSI_SQL_DATETIME_LITERALS
      60             :         case SQL_ANSI_SQL_DATETIME_LITERALS:
      61             :                 name = "SQL_ANSI_SQL_DATETIME_LITERALS";
      62             :                 category = "Supported SQL";
      63             :                 break;
      64             : #endif
      65             :         case SQL_COLLATION_SEQ:
      66             :                 name = "SQL_COLLATION_SEQ";
      67             :                 category = "Data Source Information";
      68             :                 break;
      69           0 :         case SQL_CONVERT_BIGINT:
      70           0 :                 name = "SQL_CONVERT_BIGINT";
      71           0 :                 category = "Conversion Information";
      72           0 :                 break;
      73           0 :         case SQL_CONVERT_DATE:
      74           0 :                 name = "SQL_CONVERT_DATE";
      75           0 :                 category = "Conversion Information";
      76           0 :                 break;
      77           0 :         case SQL_CONVERT_DOUBLE:
      78           0 :                 name = "SQL_CONVERT_DOUBLE";
      79           0 :                 category = "Conversion Information";
      80           0 :                 break;
      81           0 :         case SQL_CONVERT_INTERVAL_DAY_TIME:
      82           0 :                 name = "SQL_CONVERT_INTERVAL_DAY_TIME";
      83           0 :                 category = "Conversion Information";
      84           0 :                 break;
      85           0 :         case SQL_CONVERT_INTERVAL_YEAR_MONTH:
      86           0 :                 name = "SQL_CONVERT_INTERVAL_YEAR_MONTH";
      87           0 :                 category = "Conversion Information";
      88           0 :                 break;
      89           0 :         case SQL_DM_VER:
      90           0 :                 name = "SQL_DM_VER";
      91           0 :                 category = "Added for ODBC 3.x";
      92           0 :                 break;
      93           0 :         case SQL_DRIVER_HLIB:
      94           0 :                 name = "SQL_DRIVER_HLIB";
      95           0 :                 category = "Driver Information";
      96           0 :                 break;
      97             : #ifdef SQL_ODBC_STANDARD_CLI_CONFORMANCE
      98             :         case SQL_ODBC_STANDARD_CLI_CONFORMANCE:
      99             :                 name = "SQL_ODBC_STANDARD_CLI_CONFORMANCE";
     100             :                 category = "Driver Information";
     101             :                 break;
     102             : #endif
     103           0 :         case SQL_USER_NAME:
     104           0 :                 name = "SQL_USER_NAME";
     105           0 :                 category = "Data Source Information";
     106           0 :                 break;
     107             :                 /* TODO extension SQL_INFO_SS_NETLIB_NAME ?? */
     108           0 :         default:
     109           0 :                 name = "unknown";
     110           0 :                 category = "unknown";
     111           0 :                 break;
     112             :         }
     113             : 
     114           0 :         tdsdump_log(TDS_DBG_INFO1, "not implemented: %s: option/type %d(%s) [category %s]\n", function_name, fType, name, category);
     115             : 
     116           0 :         return;
     117             : }
     118             : 
     119             : SQLRETURN ODBC_PUBLIC ODBC_API
     120             : SQLGetFunctions(SQLHDBC hdbc, SQLUSMALLINT fFunction, SQLUSMALLINT FAR *pfExists)
     121             : {
     122             :         int i;
     123             : 
     124           0 :         ODBC_ENTER_HDBC;
     125             : 
     126           0 :         tdsdump_log(TDS_DBG_FUNC, "SQLGetFunctions: fFunction is %d\n", fFunction);
     127           0 :         switch (fFunction) {
     128             : #if (ODBCVER >= 0x0300)
     129             :         case SQL_API_ODBC3_ALL_FUNCTIONS:
     130           0 :                 for (i = 0; i < SQL_API_ODBC3_ALL_FUNCTIONS_SIZE; ++i) {
     131           0 :                         pfExists[i] = 0;
     132             :                 }
     133             : 
     134             :                 /*
     135             :                  * every api available are contained in a macro
     136             :                  * all these macro begin with API followed by 2 letter
     137             :                  * first letter mean pre ODBC 3 (_) or ODBC 3 (3)
     138             :                  * second letter mean implemented (X) or unimplemented (_)
     139             :                  * You should copy these macro 3 times... not very good
     140             :                  * but works. Perhaps best method is build the bit array statically
     141             :                  * and then use it but I don't know how to build it...
     142             :                  */
     143             : #undef ODBC_ALL_API
     144             : #undef ODBC_COLATTRIBUTE
     145             : 
     146             : #if SQL_API_SQLCOLATTRIBUTE != SQL_API_SQLCOLATTRIBUTES
     147             : #define ODBC_COLATTRIBUTE(s) s
     148             : #else
     149             : #define ODBC_COLATTRIBUTE(s)
     150             : #endif
     151             : 
     152             : #define ODBC_ALL_API \
     153             :         API_X(SQL_API_SQLALLOCCONNECT)\
     154             :         API_X(SQL_API_SQLALLOCENV)\
     155             :         API3X(SQL_API_SQLALLOCHANDLE)\
     156             :         API_X(SQL_API_SQLALLOCSTMT)\
     157             :         API_X(SQL_API_SQLBINDCOL)\
     158             :         API_X(SQL_API_SQLBINDPARAM)\
     159             :         API_X(SQL_API_SQLBINDPARAMETER)\
     160             :         API__(SQL_API_SQLBROWSECONNECT)\
     161             :         API3_(SQL_API_SQLBULKOPERATIONS)\
     162             :         API_X(SQL_API_SQLCANCEL)\
     163             :         API3X(SQL_API_SQLCLOSECURSOR)\
     164             :         ODBC_COLATTRIBUTE(API3X(SQL_API_SQLCOLATTRIBUTE))\
     165             :         API_X(SQL_API_SQLCOLATTRIBUTES)\
     166             :         API_X(SQL_API_SQLCOLUMNPRIVILEGES)\
     167             :         API_X(SQL_API_SQLCOLUMNS)\
     168             :         API_X(SQL_API_SQLCONNECT)\
     169             :         API3X(SQL_API_SQLCOPYDESC)\
     170             :         API_X(SQL_API_SQLDESCRIBECOL)\
     171             :         API_X(SQL_API_SQLDESCRIBEPARAM)\
     172             :         API_X(SQL_API_SQLDISCONNECT)\
     173             :         API_X(SQL_API_SQLDRIVERCONNECT)\
     174             :         API3X(SQL_API_SQLENDTRAN)\
     175             :         API_X(SQL_API_SQLERROR)\
     176             :         API_X(SQL_API_SQLEXECDIRECT)\
     177             :         API_X(SQL_API_SQLEXECUTE)\
     178             :         API_X(SQL_API_SQLEXTENDEDFETCH)\
     179             :         API_X(SQL_API_SQLFETCH)\
     180             :         API3X(SQL_API_SQLFETCHSCROLL)\
     181             :         API_X(SQL_API_SQLFOREIGNKEYS)\
     182             :         API_X(SQL_API_SQLFREECONNECT)\
     183             :         API_X(SQL_API_SQLFREEENV)\
     184             :         API3X(SQL_API_SQLFREEHANDLE)\
     185             :         API_X(SQL_API_SQLFREESTMT)\
     186             :         API3X(SQL_API_SQLGETCONNECTATTR)\
     187             :         API_X(SQL_API_SQLGETCONNECTOPTION)\
     188             :         API_X(SQL_API_SQLGETCURSORNAME)\
     189             :         API_X(SQL_API_SQLGETDATA)\
     190             :         API3X(SQL_API_SQLGETDESCFIELD)\
     191             :         API3X(SQL_API_SQLGETDESCREC)\
     192             :         API3X(SQL_API_SQLGETDIAGFIELD)\
     193             :         API3X(SQL_API_SQLGETDIAGREC)\
     194             :         API3X(SQL_API_SQLGETENVATTR)\
     195             :         API_X(SQL_API_SQLGETFUNCTIONS)\
     196             :         API_X(SQL_API_SQLGETINFO)\
     197             :         API3X(SQL_API_SQLGETSTMTATTR)\
     198             :         API_X(SQL_API_SQLGETSTMTOPTION)\
     199             :         API_X(SQL_API_SQLGETTYPEINFO)\
     200             :         API_X(SQL_API_SQLMORERESULTS)\
     201             :         API_X(SQL_API_SQLNATIVESQL)\
     202             :         API_X(SQL_API_SQLNUMPARAMS)\
     203             :         API_X(SQL_API_SQLNUMRESULTCOLS)\
     204             :         API_X(SQL_API_SQLPARAMDATA)\
     205             :         API_X(SQL_API_SQLPARAMOPTIONS)\
     206             :         API_X(SQL_API_SQLPREPARE)\
     207             :         API_X(SQL_API_SQLPRIMARYKEYS)\
     208             :         API_X(SQL_API_SQLPROCEDURECOLUMNS)\
     209             :         API_X(SQL_API_SQLPROCEDURES)\
     210             :         API_X(SQL_API_SQLPUTDATA)\
     211             :         API_X(SQL_API_SQLROWCOUNT)\
     212             :         API3X(SQL_API_SQLSETCONNECTATTR)\
     213             :         API_X(SQL_API_SQLSETCONNECTOPTION)\
     214             :         API_X(SQL_API_SQLSETCURSORNAME)\
     215             :         API3X(SQL_API_SQLSETDESCFIELD)\
     216             :         API3X(SQL_API_SQLSETDESCREC)\
     217             :         API3X(SQL_API_SQLSETENVATTR)\
     218             :         API_X(SQL_API_SQLSETPARAM)\
     219             :         API_X(SQL_API_SQLSETPOS)\
     220             :         API_X(SQL_API_SQLSETSCROLLOPTIONS)\
     221             :         API3X(SQL_API_SQLSETSTMTATTR)\
     222             :         API_X(SQL_API_SQLSETSTMTOPTION)\
     223             :         API_X(SQL_API_SQLSPECIALCOLUMNS)\
     224             :         API_X(SQL_API_SQLSTATISTICS)\
     225             :         API_X(SQL_API_SQLTABLEPRIVILEGES)\
     226             :         API_X(SQL_API_SQLTABLES)\
     227             :         API_X(SQL_API_SQLTRANSACT) \
     228             :         do {} while(0)
     229             : 
     230             : #define API_X(n) if (n >= 0 && n < (16*SQL_API_ODBC3_ALL_FUNCTIONS_SIZE)) pfExists[n/16] |= (1 << n%16);
     231             : #define API__(n)
     232             : #define API3X(n) if (n >= 0 && n < (16*SQL_API_ODBC3_ALL_FUNCTIONS_SIZE)) pfExists[n/16] |= (1 << n%16);
     233             : #define API3_(n)
     234           0 :                 ODBC_ALL_API;
     235             : #undef API_X
     236             : #undef API__
     237             : #undef API3X
     238             : #undef API3_
     239             :                 break;
     240             : #endif
     241             : 
     242           0 :         case SQL_API_ALL_FUNCTIONS:
     243           0 :                 tdsdump_log(TDS_DBG_FUNC, "SQLGetFunctions: " "fFunction is SQL_API_ALL_FUNCTIONS\n");
     244           0 :                 for (i = 0; i < 100; ++i) {
     245           0 :                         pfExists[i] = SQL_FALSE;
     246             :                 }
     247             : 
     248             : #define API_X(n) if (n >= 0 && n < 100) pfExists[n] = SQL_TRUE;
     249             : #define API__(n)
     250             : #define API3X(n)
     251             : #define API3_(n)
     252           0 :                 ODBC_ALL_API;
     253             : #undef API_X
     254             : #undef API__
     255             : #undef API3X
     256             : #undef API3_
     257             :                 break;
     258             : #define API_X(n) case n:
     259             : #define API__(n)
     260             : #if (ODBCVER >= 0x300)
     261             : #define API3X(n) case n:
     262             : #else
     263             : #define API3X(n)
     264             : #endif
     265             : #define API3_(n)
     266           0 :                 ODBC_ALL_API;
     267             : #undef API_X
     268             : #undef API__
     269             : #undef API3X
     270             : #undef API3_
     271           0 :                 *pfExists = SQL_TRUE;
     272           0 :                 break;
     273           0 :         default:
     274           0 :                 *pfExists = SQL_FALSE;
     275           0 :                 break;
     276             :         }
     277           0 :         ODBC_EXIT(dbc, SQL_SUCCESS);
     278             : #undef ODBC_ALL_API
     279             : }
     280             : 
     281             : 
     282             : SQLRETURN
     283         974 : odbc_SQLGetInfo(TDS_DBC *dbc, SQLUSMALLINT fInfoType, SQLPOINTER rgbInfoValue, SQLSMALLINT cbInfoValueMax,
     284             :                 SQLSMALLINT FAR *pcbInfoValue _WIDE)
     285             : {
     286         974 :         const char *p = NULL;
     287             :         char buf[32];
     288             :         TDSSOCKET *tds;
     289         974 :         int is_ms = -1;
     290         974 :         unsigned int smajor = 6;
     291         974 :         SQLUINTEGER mssql7plus_mask = 0;
     292         974 :         int out_len = -1;
     293             : 
     294         974 :         tdsdump_log(TDS_DBG_FUNC, "odbc_SQLGetInfo(%p, %u, %p, %d, %p)\n",
     295             :                     dbc, fInfoType, rgbInfoValue, cbInfoValueMax, pcbInfoValue);
     296             : 
     297             : #define SIVAL out_len = sizeof(SQLSMALLINT), *((SQLSMALLINT *) rgbInfoValue)
     298             : #define USIVAL out_len = sizeof(SQLUSMALLINT), *((SQLUSMALLINT *) rgbInfoValue)
     299             : #define IVAL out_len = sizeof(SQLINTEGER), *((SQLINTEGER *) rgbInfoValue)
     300             : #define UIVAL out_len = sizeof(SQLUINTEGER), *((SQLUINTEGER *) rgbInfoValue)
     301             : #define ULVAL out_len = sizeof(SQLULEN), *((SQLULEN *) rgbInfoValue)
     302             : 
     303         974 :         if ((tds = dbc->tds_socket) != NULL) {
     304         934 :                 is_ms = TDS_IS_MSSQL(tds);
     305         934 :                 smajor = (tds->conn->product_version >> 24) & 0x7F;
     306         934 :                 if (is_ms && smajor >= 7)
     307         786 :                         mssql7plus_mask = ~((SQLUINTEGER) 0);
     308             :         }
     309             : 
     310         974 :         switch (fInfoType) {
     311             :         case SQL_ACCESSIBLE_PROCEDURES:
     312             :         case SQL_ACCESSIBLE_TABLES:
     313             :                 p = "Y";
     314             :                 break;
     315             :                 /* SQL_ACTIVE_CONNECTIONS renamed to SQL_MAX_DRIVER_CONNECTIONS */
     316             : #if (ODBCVER >= 0x0300)
     317           0 :         case SQL_ACTIVE_ENVIRONMENTS:
     318           0 :                 UIVAL = 0;
     319           0 :                 break;
     320             : #endif /* ODBCVER >= 0x0300 */
     321             : #if (ODBCVER >= 0x0300)
     322           0 :         case SQL_AGGREGATE_FUNCTIONS:
     323           0 :                 UIVAL = SQL_AF_ALL;
     324           0 :                 break;
     325           0 :         case SQL_ALTER_DOMAIN:
     326           0 :                 UIVAL = 0;
     327           0 :                 break;
     328             : #endif /* ODBCVER >= 0x0300 */
     329           0 :         case SQL_ALTER_TABLE:
     330           0 :                 UIVAL = SQL_AT_ADD_COLUMN | SQL_AT_ADD_COLUMN_DEFAULT | SQL_AT_ADD_COLUMN_SINGLE | SQL_AT_ADD_CONSTRAINT |
     331             :                         SQL_AT_ADD_TABLE_CONSTRAINT | SQL_AT_CONSTRAINT_NAME_DEFINITION | SQL_AT_DROP_COLUMN_RESTRICT;
     332           0 :                 break;
     333             : #if (ODBCVER >= 0x0300)
     334           0 :         case SQL_ASYNC_MODE:
     335             :                 /* TODO we hope so in a not-too-far future */
     336             :                 /* UIVAL = SQL_AM_STATEMENT; */
     337           0 :                 UIVAL = SQL_AM_NONE;
     338           0 :                 break;
     339           0 :         case SQL_BATCH_ROW_COUNT:
     340           0 :                 UIVAL = SQL_BRC_EXPLICIT;
     341           0 :                 break;
     342           0 :         case SQL_BATCH_SUPPORT:
     343           0 :                 UIVAL = SQL_BS_ROW_COUNT_EXPLICIT | SQL_BS_ROW_COUNT_PROC | SQL_BS_SELECT_EXPLICIT | SQL_BS_SELECT_PROC;
     344           0 :                 break;
     345             : #endif /* ODBCVER >= 0x0300 */
     346           0 :         case SQL_BOOKMARK_PERSISTENCE:
     347             :                 /* TODO ??? */
     348           0 :                 UIVAL = SQL_BP_DELETE | SQL_BP_SCROLL | SQL_BP_UPDATE;
     349           0 :                 break;
     350           0 :         case SQL_CATALOG_LOCATION:
     351           0 :                 SIVAL = SQL_CL_START;
     352           0 :                 break;
     353             : #if (ODBCVER >= 0x0300)
     354             :         case SQL_CATALOG_NAME:
     355             :                 p = "Y";
     356             :                 break;
     357             : #endif /* ODBCVER >= 0x0300 */
     358           0 :         case SQL_CATALOG_NAME_SEPARATOR:
     359           0 :                 p = ".";
     360           0 :                 break;
     361           0 :         case SQL_CATALOG_TERM:
     362           0 :                 p = "database";
     363           0 :                 break;
     364           0 :         case SQL_CATALOG_USAGE:
     365           0 :                 UIVAL = SQL_CU_DML_STATEMENTS | SQL_CU_PROCEDURE_INVOCATION | SQL_CU_TABLE_DEFINITION;
     366           0 :                 break;
     367             :                 /* TODO */
     368             : #if 0
     369             :         case SQL_COLLATION_SEQ:
     370             :                 break;
     371             : #endif
     372             :         case SQL_COLUMN_ALIAS:
     373             :                 p = "Y";
     374             :                 break;
     375           0 :         case SQL_CONCAT_NULL_BEHAVIOR:
     376           0 :                 if (is_ms == -1)
     377             :                         return SQL_ERROR;
     378             :                 /* TODO a bit more complicate for mssql2k.. */
     379           0 :                 SIVAL = (!is_ms || smajor < 7) ? SQL_CB_NON_NULL : SQL_CB_NULL;
     380           0 :                 break;
     381             :                 /* TODO SQL_CONVERT_BIGINT SQL_CONVERT_GUID SQL_CONVERT_DATE SQL_CONVERT_TIME */
     382             :                 /* For Sybase/MSSql6.x we return 0 cause NativeSql is not so implemented */
     383           0 :         case SQL_CONVERT_BINARY:
     384           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_VARCHAR |
     385             :                          SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_TINYINT | SQL_CVT_LONGVARBINARY | SQL_CVT_WCHAR |
     386           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     387           0 :                 break;
     388           0 :         case SQL_CONVERT_BIT:
     389           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     390             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT | SQL_CVT_TINYINT |
     391           0 :                          SQL_CVT_WCHAR | SQL_CVT_WVARCHAR) & mssql7plus_mask;
     392           0 :                 break;
     393           0 :         case SQL_CONVERT_CHAR:
     394           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     395             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT |
     396             :                          SQL_CVT_TINYINT | SQL_CVT_TIMESTAMP | SQL_CVT_LONGVARBINARY | SQL_CVT_WCHAR | SQL_CVT_WLONGVARCHAR |
     397           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     398           0 :                 break;
     399           0 :         case SQL_CONVERT_DECIMAL:
     400           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     401             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT | SQL_CVT_TINYINT |
     402           0 :                          SQL_CVT_WCHAR | SQL_CVT_WVARCHAR) & mssql7plus_mask;
     403           0 :                 break;
     404           0 :         case SQL_CONVERT_FLOAT:
     405           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     406           0 :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_WCHAR | SQL_CVT_WVARCHAR) &
     407             :                         mssql7plus_mask;
     408           0 :                 break;
     409           0 :         case SQL_CONVERT_INTEGER:
     410           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     411             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT | SQL_CVT_TINYINT |
     412           0 :                          SQL_CVT_WCHAR | SQL_CVT_WVARCHAR) & mssql7plus_mask;
     413           0 :                 break;
     414           0 :         case SQL_CONVERT_LONGVARCHAR:
     415           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR | SQL_CVT_WCHAR | SQL_CVT_WLONGVARCHAR |
     416           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     417           0 :                 break;
     418           0 :         case SQL_CONVERT_NUMERIC:
     419           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     420             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT | SQL_CVT_TINYINT |
     421           0 :                          SQL_CVT_WCHAR | SQL_CVT_WVARCHAR) & mssql7plus_mask;
     422           0 :                 break;
     423           0 :         case SQL_CONVERT_REAL:
     424           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     425           0 :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_WCHAR | SQL_CVT_WVARCHAR) &
     426             :                         mssql7plus_mask;
     427           0 :                 break;
     428           0 :         case SQL_CONVERT_SMALLINT:
     429           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     430             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT | SQL_CVT_TINYINT |
     431           0 :                          SQL_CVT_WCHAR | SQL_CVT_WVARCHAR) & mssql7plus_mask;
     432           0 :                 break;
     433           0 :         case SQL_CONVERT_TIMESTAMP:
     434           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_VARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_TIMESTAMP | SQL_CVT_WCHAR |
     435           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     436           0 :                 break;
     437           0 :         case SQL_CONVERT_TINYINT:
     438           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     439             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT | SQL_CVT_TINYINT |
     440           0 :                          SQL_CVT_WCHAR | SQL_CVT_WVARCHAR) & mssql7plus_mask;
     441           0 :                 break;
     442           0 :         case SQL_CONVERT_VARBINARY:
     443           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_VARCHAR |
     444             :                          SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_TINYINT | SQL_CVT_LONGVARBINARY | SQL_CVT_WCHAR |
     445           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     446           0 :                 break;
     447           0 :         case SQL_CONVERT_VARCHAR:
     448           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     449             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT |
     450             :                          SQL_CVT_TINYINT | SQL_CVT_TIMESTAMP | SQL_CVT_LONGVARBINARY | SQL_CVT_WCHAR | SQL_CVT_WLONGVARCHAR |
     451           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     452           0 :                 break;
     453           0 :         case SQL_CONVERT_LONGVARBINARY:
     454           0 :                 UIVAL = (SQL_CVT_BINARY | SQL_CVT_LONGVARBINARY | SQL_CVT_VARBINARY) & mssql7plus_mask;
     455           0 :                 break;
     456           0 :         case SQL_CONVERT_WLONGVARCHAR:
     457           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR | SQL_CVT_WCHAR | SQL_CVT_WLONGVARCHAR |
     458           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     459           0 :                 break;
     460             : #if (ODBCVER >= 0x0300)
     461           0 :         case SQL_CONVERT_WCHAR:
     462           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     463             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT |
     464             :                          SQL_CVT_TINYINT | SQL_CVT_TIMESTAMP | SQL_CVT_LONGVARBINARY | SQL_CVT_WCHAR | SQL_CVT_WLONGVARCHAR |
     465           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     466           0 :                 break;
     467           0 :         case SQL_CONVERT_WVARCHAR:
     468           0 :                 UIVAL = (SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT |
     469             :                          SQL_CVT_REAL | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR | SQL_CVT_BINARY | SQL_CVT_VARBINARY | SQL_CVT_BIT |
     470             :                          SQL_CVT_TINYINT | SQL_CVT_TIMESTAMP | SQL_CVT_LONGVARBINARY | SQL_CVT_WCHAR | SQL_CVT_WLONGVARCHAR |
     471           0 :                          SQL_CVT_WVARCHAR) & mssql7plus_mask;
     472           0 :                 break;
     473             : #endif /* ODBCVER >= 0x0300 */
     474           0 :         case SQL_CONVERT_FUNCTIONS:
     475             :                 /* TODO no CAST for Sybase ?? */
     476           0 :                 UIVAL = SQL_FN_CVT_CONVERT | SQL_FN_CVT_CAST;
     477           0 :                 break;
     478             : #if (ODBCVER >= 0x0300)
     479           0 :         case SQL_CREATE_ASSERTION:
     480             :         case SQL_CREATE_CHARACTER_SET:
     481             :         case SQL_CREATE_COLLATION:
     482             :         case SQL_CREATE_DOMAIN:
     483           0 :                 UIVAL = 0;
     484           0 :                 break;
     485           0 :         case SQL_CREATE_SCHEMA:
     486           0 :                 UIVAL = SQL_CS_AUTHORIZATION | SQL_CS_CREATE_SCHEMA;
     487           0 :                 break;
     488           0 :         case SQL_CREATE_TABLE:
     489           0 :                 UIVAL = SQL_CT_CREATE_TABLE;
     490           0 :                 break;
     491           0 :         case SQL_CREATE_TRANSLATION:
     492           0 :                 UIVAL = 0;
     493           0 :                 break;
     494           0 :         case SQL_CREATE_VIEW:
     495           0 :                 UIVAL = SQL_CV_CHECK_OPTION | SQL_CV_CREATE_VIEW;
     496           0 :                 break;
     497             : #endif /* ODBCVER >= 0x0300 */
     498           0 :         case SQL_CORRELATION_NAME:
     499           0 :                 USIVAL = SQL_CN_ANY;
     500           0 :                 break;
     501           0 :         case SQL_CURSOR_COMMIT_BEHAVIOR:
     502             :                 /* currently cursors are not supported however sql server close automaticly cursors on commit */
     503             :                 /* TODO cursors test what happen if rollback, cursors get properly deleted ?? */
     504           0 :                 USIVAL = SQL_CB_CLOSE;
     505           0 :                 break;
     506           0 :         case SQL_CURSOR_ROLLBACK_BEHAVIOR:
     507           0 :                 USIVAL = SQL_CB_CLOSE;
     508           0 :                 break;
     509           0 :         case SQL_CURSOR_SENSITIVITY:
     510           0 :                 UIVAL = SQL_SENSITIVE;
     511           0 :                 break;
     512           0 :         case SQL_DATABASE_NAME:
     513           0 :                 p = tds_dstr_cstr(&dbc->attr.current_catalog);
     514           0 :                 break;
     515           0 :         case SQL_DATA_SOURCE_NAME:
     516           0 :                 p = tds_dstr_cstr(&dbc->dsn);
     517           0 :                 break;
     518           0 :         case SQL_DATA_SOURCE_READ_ONLY:
     519             :                 /*
     520             :                  * TODO: determine the right answer from connection
     521             :                  * attribute SQL_ATTR_ACCESS_MODE
     522             :                  */
     523           0 :                 p = "N";      /* false, writable */
     524           0 :                 break;
     525             : #if (ODBCVER >= 0x0300)
     526           0 :         case SQL_DATETIME_LITERALS:
     527             :                 /* TODO ok ?? */
     528           0 :                 UIVAL = 0;
     529           0 :                 break;
     530             : #endif /* ODBCVER >= 0x0300 */
     531         278 :         case SQL_DBMS_NAME:
     532         278 :                 p = tds ? tds->conn->product_name : NULL;
     533             :                 break;
     534         106 :         case SQL_DBMS_VER:
     535         106 :                 if (!dbc->tds_socket)
     536             :                         return SQL_ERROR;
     537         106 :                 odbc_rdbms_version(dbc->tds_socket, buf);
     538         106 :                 p = buf;
     539         106 :                 break;
     540             : #if (ODBCVER >= 0x0300)
     541           0 :         case SQL_DDL_INDEX:
     542           0 :                 UIVAL = 0;
     543           0 :                 break;
     544             : #endif /* ODBCVER >= 0x0300 */
     545           0 :         case SQL_DEFAULT_TXN_ISOLATION:
     546           0 :                 UIVAL = SQL_TXN_READ_COMMITTED;
     547           0 :                 break;
     548             : #if (ODBCVER >= 0x0300)
     549             :         case SQL_DESCRIBE_PARAMETER:
     550             :                 p = "Y";
     551             :                 break;
     552             : #endif /* ODBCVER >= 0x0300 */
     553          10 :         case SQL_DRIVER_HDBC:
     554          10 :                 ULVAL = (SQLULEN) dbc;
     555          10 :                 break;
     556          10 :         case SQL_DRIVER_HENV:
     557          10 :                 ULVAL = (SQLULEN) dbc->env;
     558          10 :                 break;
     559           0 :         case SQL_DRIVER_HSTMT:{
     560           0 :                         void *ptr = *((void **) rgbInfoValue);
     561             : 
     562           0 :                         if (SQL_NULL_HSTMT != ptr && !IS_HSTMT(ptr))
     563           0 :                                 ULVAL = SQL_NULL_HSTMT;
     564             :                 }
     565             :                 break;
     566           0 :         case SQL_DRIVER_HDESC:{
     567           0 :                         void *ptr = *((void **) rgbInfoValue);
     568             : 
     569           0 :                         if (SQL_NULL_HDESC != ptr && !IS_HDESC(ptr))
     570           0 :                                 ULVAL = SQL_NULL_HDESC;
     571             :                 }
     572             :                 break;
     573         356 :         case SQL_DRIVER_NAME:   /* ODBC 2.0 */
     574         356 :                 p = "libtdsodbc.so";
     575         356 :                 break;
     576           0 :         case SQL_DRIVER_ODBC_VER:
     577           0 :                 p = "03.50";
     578           0 :                 break;
     579           0 :         case SQL_DRIVER_VER:
     580           0 :                 sprintf(buf, "%02d.%02d.%04d", TDS_VERSION_MAJOR, TDS_VERSION_MINOR, TDS_VERSION_SUBVERSION);
     581           0 :                 p = buf;
     582           0 :                 break;
     583             : #if (ODBCVER >= 0x0300)
     584           0 :         case SQL_DROP_ASSERTION:
     585             :         case SQL_DROP_CHARACTER_SET:
     586             :         case SQL_DROP_COLLATION:
     587             :         case SQL_DROP_DOMAIN:
     588             :         case SQL_DROP_SCHEMA:
     589           0 :                 UIVAL = 0;
     590           0 :                 break;
     591           0 :         case SQL_DROP_TABLE:
     592           0 :                 UIVAL = SQL_DT_DROP_TABLE;
     593           0 :                 break;
     594           0 :         case SQL_DROP_TRANSLATION:
     595           0 :                 UIVAL = 0;
     596           0 :                 break;
     597           0 :         case SQL_DROP_VIEW:
     598           0 :                 UIVAL = SQL_DV_DROP_VIEW;
     599           0 :                 break;
     600           0 :         case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
     601           0 :                 if (dbc->cursor_support)
     602             :                         /* TODO cursor SQL_CA1_BULK_ADD SQL_CA1_POS_REFRESH SQL_CA1_SELECT_FOR_UPDATE */
     603           0 :                         UIVAL = SQL_CA1_ABSOLUTE | SQL_CA1_NEXT | SQL_CA1_RELATIVE |
     604             :                                 SQL_CA1_LOCK_NO_CHANGE |
     605             :                                 SQL_CA1_POS_DELETE | SQL_CA1_POS_POSITION | SQL_CA1_POS_UPDATE |
     606             :                                 SQL_CA1_POSITIONED_UPDATE | SQL_CA1_POSITIONED_DELETE;
     607             :                 else
     608           0 :                         UIVAL = 0;
     609             :                 break;
     610           0 :         case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
     611             :                 /* TODO cursors */
     612             :                 /* Cursors not supported yet */
     613             :                 /*
     614             :                  * Should be SQL_CA2_LOCK_CONCURRENCY SQL_CA2_MAX_ROWS_CATALOG SQL_CA2_MAX_ROWS_DELETE
     615             :                  * SQL_CA2_MAX_ROWS_INSERT SQL_CA2_MAX_ROWS_SELECT SQL_CA2_MAX_ROWS_UPDATE SQL_CA2_OPT_ROWVER_CONCURRENCY
     616             :                  * SQL_CA2_OPT_VALUES_CONCURRENCY SQL_CA2_READ_ONLY_CONCURRENCY SQL_CA2_SENSITIVITY_ADDITIONS
     617             :                  * SQL_CA2_SENSITIVITY_UPDATES SQL_CA2_SIMULATE_UNIQUE
     618             :                  */
     619           0 :                 UIVAL = 0;
     620           0 :                 break;
     621             : #endif /* ODBCVER >= 0x0300 */
     622             :         case SQL_EXPRESSIONS_IN_ORDERBY:
     623             :                 p = "Y";
     624             :                 break;
     625           0 :         case SQL_FILE_USAGE:
     626           0 :                 USIVAL = SQL_FILE_NOT_SUPPORTED;
     627           0 :                 break;
     628           0 :         case SQL_FETCH_DIRECTION:
     629           0 :                 if (dbc->cursor_support)
     630             :                         /* TODO cursors SQL_FD_FETCH_BOOKMARK */
     631           0 :                         UIVAL = SQL_FD_FETCH_ABSOLUTE | SQL_FD_FETCH_FIRST | SQL_FD_FETCH_LAST | SQL_FD_FETCH_NEXT
     632             :                                 | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_RELATIVE;
     633             :                 else
     634           0 :                         UIVAL = 0;
     635             :                 break;
     636             : #if (ODBCVER >= 0x0300)
     637           0 :         case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
     638           0 :                 if (dbc->cursor_support)
     639             :                         /* TODO cursors SQL_CA1_SELECT_FOR_UPDATE */
     640           0 :                         UIVAL = SQL_CA1_NEXT | SQL_CA1_POSITIONED_DELETE | SQL_CA1_POSITIONED_UPDATE;
     641             :                 else
     642           0 :                         UIVAL = 0;
     643             :                 break;
     644           0 :         case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
     645             :                 /* TODO cursors */
     646             :                 /* Cursors not supported yet */
     647             :                 /*
     648             :                  * Should be SQL_CA2_LOCK_CONCURRENCY SQL_CA2_MAX_ROWS_CATALOG SQL_CA2_MAX_ROWS_DELETE
     649             :                  * SQL_CA2_MAX_ROWS_INSERT SQL_CA2_MAX_ROWS_SELECT SQL_CA2_MAX_ROWS_UPDATE SQL_CA2_OPT_ROWVER_CONCURRENCY
     650             :                  * SQL_CA2_OPT_VALUES_CONCURRENCY SQL_CA2_READ_ONLY_CONCURRENCY
     651             :                  */
     652           0 :                 UIVAL = 0;
     653           0 :                 break;
     654             : #endif /* ODBCVER >= 0x0300 */
     655           0 :         case SQL_GETDATA_EXTENSIONS:
     656             :                 /* TODO FreeTDS support more ?? */
     657           0 :                 UIVAL = SQL_GD_BLOCK;
     658           0 :                 break;
     659           0 :         case SQL_GROUP_BY:
     660           0 :                 USIVAL = SQL_GB_GROUP_BY_CONTAINS_SELECT;
     661           0 :                 break;
     662           0 :         case SQL_IDENTIFIER_CASE:
     663             :                 /* TODO configuration dependend */
     664           0 :                 USIVAL = SQL_IC_MIXED;
     665           0 :                 break;
     666           0 :         case SQL_IDENTIFIER_QUOTE_CHAR:
     667           0 :                 p = "\"";
     668             :                 /* TODO workaround for Sybase, use SET QUOTED_IDENTIFIER ON and fix unwanted quote */
     669           0 :                 if (!is_ms)
     670           0 :                         p = "";
     671             :                 break;
     672             : #if (ODBCVER >= 0x0300)
     673           0 :         case SQL_INDEX_KEYWORDS:
     674           0 :                 UIVAL = SQL_IK_ASC | SQL_IK_DESC;
     675           0 :                 break;
     676             : #endif /* ODBCVER >= 0x0300 */
     677           0 :         case SQL_INFO_SCHEMA_VIEWS:
     678             :                 /* TODO finish */
     679           0 :                 UIVAL = 0;
     680           0 :                 break;
     681           0 :         case SQL_INSERT_STATEMENT:
     682           0 :                 UIVAL = 0;
     683           0 :                 break;
     684             :                 /* renamed from SQL_ODBC_SQL_OPT_IEF */
     685             :         case SQL_INTEGRITY:
     686             :                 p = "Y";
     687             :                 break;
     688           0 :         case SQL_KEYSET_CURSOR_ATTRIBUTES1:
     689             :         case SQL_KEYSET_CURSOR_ATTRIBUTES2:
     690             :                 /* TODO cursors */
     691           0 :                 UIVAL = 0;
     692           0 :                 break;
     693           0 :         case SQL_KEYWORDS:
     694             :                 /* TODO ok for Sybase ? */
     695           0 :                 p = "BREAK,BROWSE,BULK,CHECKPOINT,CLUSTERED,"
     696             :                         "COMMITTED,COMPUTE,CONFIRM,CONTROLROW,DATABASE,"
     697             :                         "DBCC,DISK,DISTRIBUTED,DUMMY,DUMP,ERRLVL,"
     698             :                         "ERROREXIT,EXIT,FILE,FILLFACTOR,FLOPPY,HOLDLOCK,"
     699             :                         "IDENTITY_INSERT,IDENTITYCOL,IF,KILL,LINENO,"
     700             :                         "LOAD,MIRROREXIT,NONCLUSTERED,OFF,OFFSETS,ONCE,"
     701             :                         "OVER,PERCENT,PERM,PERMANENT,PLAN,PRINT,PROC,"
     702             :                         "PROCESSEXIT,RAISERROR,READ,READTEXT,RECONFIGURE,"
     703             :                         "REPEATABLE,RETURN,ROWCOUNT,RULE,SAVE,SERIALIZABLE,"
     704             :                         "SETUSER,SHUTDOWN,STATISTICS,TAPE,TEMP,TEXTSIZE,"
     705             :                         "TRAN,TRIGGER,TRUNCATE,TSEQUEL,UNCOMMITTED," "UPDATETEXT,USE,WAITFOR,WHILE,WRITETEXT";
     706           0 :                 break;
     707             :         case SQL_LIKE_ESCAPE_CLAUSE:
     708             :                 p = "Y";
     709             :                 break;
     710           0 :         case SQL_LOCK_TYPES:
     711           0 :                 if (dbc->cursor_support)
     712           0 :                         IVAL = SQL_LCK_NO_CHANGE;
     713             :                 else
     714           0 :                         IVAL = 0;
     715             :                 break;
     716             : #if (ODBCVER >= 0x0300)
     717           0 :         case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS:
     718           0 :                 UIVAL = 1;
     719           0 :                 break;
     720             : #endif /* ODBCVER >= 0x0300 */
     721             :                 /* TODO same limits for Sybase ? */
     722           0 :         case SQL_MAX_BINARY_LITERAL_LEN:
     723           0 :                 UIVAL = 131072;
     724           0 :                 break;
     725           0 :         case SQL_MAX_CHAR_LITERAL_LEN:
     726           0 :                 UIVAL = 131072;
     727           0 :                 break;
     728           0 :         case SQL_MAX_CONCURRENT_ACTIVITIES:
     729           0 :                 USIVAL = 1;
     730           0 :                 break;
     731           0 :         case SQL_MAX_COLUMNS_IN_GROUP_BY:
     732             :         case SQL_MAX_COLUMNS_IN_INDEX:
     733             :         case SQL_MAX_COLUMNS_IN_ORDER_BY:
     734             :                 /* TODO Sybase ? */
     735           0 :                 USIVAL = 16;
     736           0 :                 break;
     737           0 :         case SQL_MAX_COLUMNS_IN_SELECT:
     738             :                 /* TODO Sybase ? */
     739           0 :                 USIVAL = 4000;
     740           0 :                 break;
     741           0 :         case SQL_MAX_COLUMNS_IN_TABLE:
     742             :                 /* TODO Sybase ? */
     743           0 :                 USIVAL = 250;
     744           0 :                 break;
     745           0 :         case SQL_MAX_DRIVER_CONNECTIONS:
     746           0 :                 USIVAL = 0;
     747           0 :                 break;
     748           0 :         case SQL_MAX_IDENTIFIER_LEN:
     749           0 :                 if (is_ms == -1)
     750             :                         return SQL_ERROR;
     751           0 :                 USIVAL = (!is_ms || smajor < 7) ? 30 : 128;
     752           0 :                 break;
     753           0 :         case SQL_MAX_INDEX_SIZE:
     754           0 :                 UIVAL = 127;
     755           0 :                 break;
     756           0 :         case SQL_MAX_PROCEDURE_NAME_LEN:
     757           0 :                 if (is_ms == -1)
     758             :                         return SQL_ERROR;
     759             :                 /* TODO Sybase ? */
     760           0 :                 USIVAL = (is_ms && smajor >= 7) ? 134 : 36;
     761           0 :                 break;
     762           0 :         case SQL_MAX_ROW_SIZE:
     763           0 :                 if (is_ms == -1)
     764             :                         return SQL_ERROR;
     765             :                 /* TODO Sybase ? */
     766           0 :                 UIVAL = (is_ms && smajor >= 7) ? 8062 : 1962;
     767           0 :                 break;
     768           0 :         case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
     769           0 :                 p = "N";
     770           0 :                 break;
     771           0 :         case SQL_MAX_STATEMENT_LEN:
     772             :                 /* TODO Sybase ? */
     773           0 :                 UIVAL = 131072;
     774           0 :                 break;
     775           0 :         case SQL_MAX_TABLES_IN_SELECT:
     776             :                 /* TODO Sybase ? */
     777           0 :                 USIVAL = 16;
     778           0 :                 break;
     779           0 :         case SQL_MAX_USER_NAME_LEN:
     780             :                 /* TODO Sybase ? */
     781           0 :                 if (is_ms == -1)
     782             :                         return SQL_ERROR;
     783           0 :                 USIVAL = (is_ms && smajor >= 7) ? 128 : 30;
     784           0 :                 break;
     785           0 :         case SQL_MAX_COLUMN_NAME_LEN:
     786             :         case SQL_MAX_CURSOR_NAME_LEN:
     787             :         case SQL_MAX_SCHEMA_NAME_LEN:
     788             :         case SQL_MAX_CATALOG_NAME_LEN:
     789             :         case SQL_MAX_TABLE_NAME_LEN:
     790             :                 /* TODO Sybase ? */
     791           0 :                 if (is_ms == -1)
     792             :                         return SQL_ERROR;
     793           0 :                 USIVAL = (is_ms && smajor >= 7) ? 128 : 30;
     794           0 :                 break;
     795             :         case SQL_MULT_RESULT_SETS:
     796             :                 p = "Y";
     797             :                 break;
     798             :         case SQL_MULTIPLE_ACTIVE_TXN:
     799             :                 p = "Y";
     800             :                 break;
     801             :         case SQL_NEED_LONG_DATA_LEN:
     802             :                 /* current implementation do not require length, however future will, so is correct to return yes */
     803             :                 p = "Y";
     804             :                 break;
     805           0 :         case SQL_NON_NULLABLE_COLUMNS:
     806           0 :                 USIVAL = SQL_NNC_NON_NULL;
     807           0 :                 break;
     808           0 :         case SQL_NULL_COLLATION:
     809           0 :                 USIVAL = SQL_NC_LOW;
     810           0 :                 break;
     811           0 :         case SQL_NUMERIC_FUNCTIONS:
     812           0 :                 UIVAL = (SQL_FN_NUM_ABS | SQL_FN_NUM_ACOS | SQL_FN_NUM_ASIN | SQL_FN_NUM_ATAN | SQL_FN_NUM_ATAN2 |
     813             :                          SQL_FN_NUM_CEILING | SQL_FN_NUM_COS | SQL_FN_NUM_COT | SQL_FN_NUM_DEGREES | SQL_FN_NUM_EXP |
     814             :                          SQL_FN_NUM_FLOOR | SQL_FN_NUM_LOG | SQL_FN_NUM_LOG10 | SQL_FN_NUM_MOD | SQL_FN_NUM_PI | SQL_FN_NUM_POWER |
     815             :                          SQL_FN_NUM_RADIANS | SQL_FN_NUM_RAND | SQL_FN_NUM_ROUND | SQL_FN_NUM_SIGN | SQL_FN_NUM_SIN |
     816           0 :                          SQL_FN_NUM_SQRT | SQL_FN_NUM_TAN) & mssql7plus_mask;
     817           0 :                 break;
     818           0 :         case SQL_ODBC_API_CONFORMANCE:
     819           0 :                 SIVAL = SQL_OAC_LEVEL2;
     820           0 :                 break;
     821             : #if (ODBCVER >= 0x0300)
     822           0 :         case SQL_ODBC_INTERFACE_CONFORMANCE:
     823           0 :                 UIVAL = SQL_OAC_LEVEL2;
     824           0 :                 break;
     825             : #endif /* ODBCVER >= 0x0300 */
     826           0 :         case SQL_ODBC_SAG_CLI_CONFORMANCE:
     827           0 :                 SIVAL = SQL_OSCC_NOT_COMPLIANT;
     828           0 :                 break;
     829           0 :         case SQL_ODBC_SQL_CONFORMANCE:
     830           0 :                 SIVAL = SQL_OSC_CORE;
     831           0 :                 break;
     832             : #ifdef TDS_NO_DM
     833           0 :         case SQL_ODBC_VER:
     834             :                 /* TODO check format ##.##.0000 */
     835           0 :                 p = VERSION;
     836           0 :                 break;
     837             : #endif
     838             : #if (ODBCVER >= 0x0300)
     839           0 :         case SQL_OJ_CAPABILITIES:
     840           0 :                 UIVAL = SQL_OJ_ALL_COMPARISON_OPS | SQL_OJ_FULL | SQL_OJ_INNER | SQL_OJ_LEFT | SQL_OJ_NESTED | SQL_OJ_NOT_ORDERED |
     841             :                         SQL_OJ_RIGHT;
     842           0 :                 break;
     843             : #endif /* ODBCVER >= 0x0300 */
     844           0 :         case SQL_ORDER_BY_COLUMNS_IN_SELECT:
     845           0 :                 p = "N";
     846           0 :                 break;
     847             :         case SQL_OUTER_JOINS:
     848             :                 p = "Y";
     849             :                 break;
     850             : #if (ODBCVER >= 0x0300)
     851           0 :         case SQL_PARAM_ARRAY_ROW_COUNTS:
     852           0 :                 UIVAL = SQL_PARC_BATCH;
     853           0 :                 break;
     854           0 :         case SQL_PARAM_ARRAY_SELECTS:
     855           0 :                 UIVAL = SQL_PAS_BATCH;
     856           0 :                 break;
     857             : #endif /* ODBCVER >= 0x0300 */
     858           0 :         case SQL_POS_OPERATIONS:
     859           0 :                 if (dbc->cursor_support)
     860             :                         /* TODO cursors SQL_POS_ADD SQL_POS_REFRESH */
     861             :                         /* test REFRESH, ADD under mssql, under Sybase I don't know how to do it but dblib do */
     862           0 :                         IVAL = SQL_POS_DELETE | SQL_POS_POSITION | SQL_POS_UPDATE;
     863             :                 else
     864           0 :                         IVAL = 0;
     865             :                 break;
     866           0 :         case SQL_POSITIONED_STATEMENTS:
     867             :                 /* TODO cursors SQL_PS_SELECT_FOR_UPDATE */
     868           0 :                 IVAL = SQL_PS_POSITIONED_DELETE | SQL_PS_POSITIONED_UPDATE;
     869           0 :                 break;
     870           0 :         case SQL_PROCEDURE_TERM:
     871           0 :                 p = "stored procedure";
     872           0 :                 break;
     873             :         case SQL_PROCEDURES:
     874             :                 p = "Y";
     875             :                 break;
     876           0 :         case SQL_QUOTED_IDENTIFIER_CASE:
     877             :                 /* TODO usually insensitive */
     878           0 :                 USIVAL = SQL_IC_MIXED;
     879           0 :                 break;
     880           0 :         case SQL_ROW_UPDATES:
     881           0 :                 p = "N";
     882           0 :                 break;
     883             : #if (ODBCVER >= 0x0300)
     884           0 :         case SQL_SCHEMA_TERM:
     885           0 :                 p = "owner";
     886           0 :                 break;
     887           0 :         case SQL_SCHEMA_USAGE:
     888           0 :                 UIVAL = SQL_OU_DML_STATEMENTS | SQL_OU_INDEX_DEFINITION | SQL_OU_PRIVILEGE_DEFINITION | SQL_OU_PROCEDURE_INVOCATION
     889             :                         | SQL_OU_TABLE_DEFINITION;
     890           0 :                 break;
     891             : #endif /* ODBCVER >= 0x0300 */
     892           0 :         case SQL_SCROLL_CONCURRENCY:
     893           0 :                 if (dbc->cursor_support)
     894             :                         /* TODO cursors test them, Sybase support all ?  */
     895           0 :                         IVAL = SQL_SCCO_LOCK | SQL_SCCO_OPT_ROWVER | SQL_SCCO_OPT_VALUES | SQL_SCCO_READ_ONLY;
     896             :                 else
     897           0 :                         IVAL = SQL_SCCO_READ_ONLY;
     898             :                 break;
     899           0 :         case SQL_SCROLL_OPTIONS:
     900           0 :                 if (dbc->cursor_support)
     901             :                         /* TODO cursors test them, Sybase support all ?? */
     902           0 :                         UIVAL = SQL_SO_DYNAMIC | SQL_SO_FORWARD_ONLY | SQL_SO_KEYSET_DRIVEN | SQL_SO_STATIC;
     903             :                 else
     904           0 :                         UIVAL = SQL_SO_FORWARD_ONLY | SQL_SO_STATIC;
     905             :                 break;
     906           0 :         case SQL_SEARCH_PATTERN_ESCAPE:
     907           0 :                 p = "\\";
     908           0 :                 break;
     909           0 :         case SQL_SERVER_NAME:
     910           0 :                 p = dbc->tds_socket->conn->server;
     911           0 :                 break;
     912           0 :         case SQL_SPECIAL_CHARACTERS:
     913             :                 /* TODO others ?? */
     914           0 :                 p = "\'\"[]{}";
     915           0 :                 break;
     916             : #if (ODBCVER >= 0x0300)
     917           0 :         case SQL_SQL_CONFORMANCE:
     918           0 :                 UIVAL = SQL_SC_SQL92_ENTRY;
     919           0 :                 break;
     920           0 :         case SQL_SQL92_DATETIME_FUNCTIONS:
     921             :         case SQL_SQL92_FOREIGN_KEY_DELETE_RULE:
     922             :         case SQL_SQL92_FOREIGN_KEY_UPDATE_RULE:
     923           0 :                 UIVAL = 0;
     924           0 :                 break;
     925           0 :         case SQL_SQL92_GRANT:
     926           0 :                 UIVAL = SQL_SG_WITH_GRANT_OPTION;
     927           0 :                 break;
     928           0 :         case SQL_SQL92_NUMERIC_VALUE_FUNCTIONS:
     929           0 :                 UIVAL = 0;
     930           0 :                 break;
     931           0 :         case SQL_SQL92_PREDICATES:
     932             :                 /* TODO Sybase ?? */
     933           0 :                 UIVAL = SQL_SP_EXISTS | SQL_SP_ISNOTNULL | SQL_SP_ISNULL;
     934           0 :                 break;
     935           0 :         case SQL_SQL92_RELATIONAL_JOIN_OPERATORS:
     936             :                 /* TODO Sybase ?? */
     937           0 :                 UIVAL = SQL_SRJO_CROSS_JOIN | SQL_SRJO_FULL_OUTER_JOIN | SQL_SRJO_INNER_JOIN | SQL_SRJO_LEFT_OUTER_JOIN |
     938             :                         SQL_SRJO_RIGHT_OUTER_JOIN | SQL_SRJO_UNION_JOIN;
     939           0 :                 break;
     940           0 :         case SQL_SQL92_REVOKE:
     941           0 :                 UIVAL = SQL_SR_GRANT_OPTION_FOR;
     942           0 :                 break;
     943           0 :         case SQL_SQL92_ROW_VALUE_CONSTRUCTOR:
     944           0 :                 UIVAL = SQL_SRVC_DEFAULT | SQL_SRVC_NULL | SQL_SRVC_ROW_SUBQUERY | SQL_SRVC_VALUE_EXPRESSION;
     945           0 :                 break;
     946           0 :         case SQL_SQL92_STRING_FUNCTIONS:
     947           0 :                 UIVAL = SQL_SSF_LOWER | SQL_SSF_UPPER;
     948           0 :                 break;
     949           0 :         case SQL_SQL92_VALUE_EXPRESSIONS:
     950             :                 /* TODO Sybase ? CAST supported ? */
     951           0 :                 UIVAL = SQL_SVE_CASE | SQL_SVE_CAST | SQL_SVE_COALESCE | SQL_SVE_NULLIF;
     952           0 :                 break;
     953           0 :         case SQL_STANDARD_CLI_CONFORMANCE:
     954           0 :                 UIVAL = SQL_SCC_ISO92_CLI;
     955           0 :                 break;
     956           0 :         case SQL_STATIC_SENSITIVITY:
     957           0 :                 IVAL = 0;
     958           0 :                 break;
     959           0 :         case SQL_STATIC_CURSOR_ATTRIBUTES1:
     960           0 :                 if (dbc->cursor_support)
     961             :                         /* TODO cursors SQL_CA1_BOOKMARK SQL_CA1_BULK_FETCH_BY_BOOKMARK SQL_CA1_POS_REFRESH */
     962           0 :                         UIVAL = SQL_CA1_ABSOLUTE | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_NEXT | SQL_CA1_POS_POSITION | SQL_CA1_RELATIVE;
     963             :                 else
     964           0 :                         UIVAL = 0;
     965             :                 break;
     966           0 :         case SQL_STATIC_CURSOR_ATTRIBUTES2:
     967             :                 /* TODO cursors */
     968           0 :                 UIVAL = 0;
     969           0 :                 break;
     970             : #endif /* ODBCVER >= 0x0300 */
     971           0 :         case SQL_STRING_FUNCTIONS:
     972           0 :                 UIVAL = (SQL_FN_STR_ASCII | SQL_FN_STR_BIT_LENGTH | SQL_FN_STR_CHAR | SQL_FN_STR_CONCAT | SQL_FN_STR_DIFFERENCE |
     973             :                          SQL_FN_STR_INSERT | SQL_FN_STR_LCASE | SQL_FN_STR_LEFT | SQL_FN_STR_LENGTH | SQL_FN_STR_LOCATE_2 |
     974             :                          SQL_FN_STR_LTRIM | SQL_FN_STR_OCTET_LENGTH | SQL_FN_STR_REPEAT | SQL_FN_STR_RIGHT | SQL_FN_STR_RTRIM |
     975           0 :                          SQL_FN_STR_SOUNDEX | SQL_FN_STR_SPACE | SQL_FN_STR_SUBSTRING | SQL_FN_STR_UCASE) & mssql7plus_mask;
     976           0 :                 break;
     977           0 :         case SQL_SUBQUERIES:
     978           0 :                 UIVAL = SQL_SQ_COMPARISON | SQL_SQ_CORRELATED_SUBQUERIES | SQL_SQ_EXISTS | SQL_SQ_IN | SQL_SQ_QUANTIFIED;
     979           0 :                 break;
     980           0 :         case SQL_SYSTEM_FUNCTIONS:
     981           0 :                 UIVAL = SQL_FN_SYS_DBNAME | SQL_FN_SYS_IFNULL | SQL_FN_SYS_USERNAME;
     982           0 :                 break;
     983           0 :         case SQL_TABLE_TERM:
     984           0 :                 p = "table";
     985           0 :                 break;
     986           0 :         case SQL_TIMEDATE_ADD_INTERVALS:
     987           0 :                 UIVAL = (SQL_FN_TSI_DAY | SQL_FN_TSI_FRAC_SECOND | SQL_FN_TSI_HOUR | SQL_FN_TSI_MINUTE | SQL_FN_TSI_MONTH |
     988           0 :                          SQL_FN_TSI_QUARTER | SQL_FN_TSI_SECOND | SQL_FN_TSI_WEEK | SQL_FN_TSI_YEAR) & mssql7plus_mask;
     989           0 :                 break;
     990           0 :         case SQL_TIMEDATE_DIFF_INTERVALS:
     991           0 :                 UIVAL = (SQL_FN_TSI_DAY | SQL_FN_TSI_FRAC_SECOND | SQL_FN_TSI_HOUR | SQL_FN_TSI_MINUTE | SQL_FN_TSI_MONTH |
     992           0 :                          SQL_FN_TSI_QUARTER | SQL_FN_TSI_SECOND | SQL_FN_TSI_WEEK | SQL_FN_TSI_YEAR) & mssql7plus_mask;
     993           0 :                 break;
     994           0 :         case SQL_TIMEDATE_FUNCTIONS:
     995           0 :                 UIVAL = (SQL_FN_TD_CURDATE | SQL_FN_TD_CURRENT_DATE | SQL_FN_TD_CURRENT_TIME | SQL_FN_TD_CURRENT_TIMESTAMP |
     996             :                          SQL_FN_TD_CURTIME | SQL_FN_TD_DAYNAME | SQL_FN_TD_DAYOFMONTH | SQL_FN_TD_DAYOFWEEK | SQL_FN_TD_DAYOFYEAR |
     997             :                          SQL_FN_TD_EXTRACT | SQL_FN_TD_HOUR | SQL_FN_TD_MINUTE | SQL_FN_TD_MONTH | SQL_FN_TD_MONTHNAME |
     998             :                          SQL_FN_TD_NOW | SQL_FN_TD_QUARTER | SQL_FN_TD_SECOND | SQL_FN_TD_TIMESTAMPADD | SQL_FN_TD_TIMESTAMPDIFF |
     999           0 :                          SQL_FN_TD_WEEK | SQL_FN_TD_YEAR) & mssql7plus_mask;
    1000           0 :                 break;
    1001           0 :         case SQL_TXN_CAPABLE:
    1002             :                 /* transaction for DML and DDL */
    1003           0 :                 SIVAL = SQL_TC_ALL;
    1004           0 :                 break;
    1005           0 :         case SQL_TXN_ISOLATION_OPTION:
    1006           0 :                 UIVAL = SQL_TXN_READ_COMMITTED | SQL_TXN_READ_UNCOMMITTED | SQL_TXN_REPEATABLE_READ | SQL_TXN_SERIALIZABLE;
    1007           0 :                 break;
    1008           0 :         case SQL_UNION:
    1009           0 :                 UIVAL = SQL_U_UNION | SQL_U_UNION_ALL;
    1010           0 :                 break;
    1011             :                 /* TODO finish */
    1012           0 :         case SQL_USER_NAME:
    1013             :                 /* TODO this is not correct username */
    1014             :                 /* p = tds_dstr_cstr(&dbc->tds_login->user_name); */
    1015             :                 /* make OpenOffice happy :) */
    1016           0 :                 p = "";
    1017           0 :                 break;
    1018           0 :         case SQL_XOPEN_CLI_YEAR:
    1019             :                 /* TODO check specifications */
    1020           0 :                 p = "1995";
    1021           0 :                 break;
    1022         134 :         case SQL_INFO_FREETDS_TDS_VERSION:
    1023         134 :                 if (!dbc->tds_socket)
    1024             :                         return SQL_ERROR;
    1025         134 :                 UIVAL = TDS_MAJOR(dbc->tds_socket->conn) << 16 | TDS_MINOR(dbc->tds_socket->conn);
    1026         134 :                 break;
    1027          80 :         case SQL_INFO_FREETDS_SOCKET:
    1028          80 :                 if (IS_TDSDEAD(dbc->tds_socket))
    1029             :                         return SQL_ERROR;
    1030          80 :                 ULVAL = dbc->tds_socket->conn->s;
    1031          80 :                 break;
    1032           0 :         default:
    1033           0 :                 odbc_log_unimplemented_type("SQLGetInfo", fInfoType);
    1034           0 :                 odbc_errs_add(&dbc->errs, "HY092", "Option not supported");
    1035           0 :                 return SQL_ERROR;
    1036             :         }
    1037             : 
    1038             :         /* char data */
    1039         974 :         if (p) {
    1040         740 :                 return odbc_set_string_oct(dbc, rgbInfoValue, cbInfoValueMax, pcbInfoValue, p, -1);
    1041             :         } else {
    1042         234 :                 if (out_len > 0 && pcbInfoValue)
    1043         214 :                         *pcbInfoValue = out_len;
    1044             :         }
    1045             : 
    1046             :         return SQL_SUCCESS;
    1047             : #undef SIVAL
    1048             : #undef USIVAL
    1049             : #undef IVAL
    1050             : #undef UIVAL
    1051             : }
    1052             : 
    1053             : SQLRETURN ODBC_PUBLIC ODBC_API
    1054             : SQLGetInfo(SQLHDBC hdbc, SQLUSMALLINT fInfoType, SQLPOINTER rgbInfoValue, SQLSMALLINT cbInfoValueMax, SQLSMALLINT FAR *pcbInfoValue)
    1055             : {
    1056         501 :         ODBC_ENTER_HDBC;
    1057             : 
    1058         501 :         tdsdump_log(TDS_DBG_FUNC, "SQLGetInfo(%p, %d, %p, %d, %p)\n", hdbc, fInfoType, rgbInfoValue, cbInfoValueMax, pcbInfoValue);
    1059             : 
    1060         501 :         ODBC_EXIT(dbc, odbc_SQLGetInfo(dbc, fInfoType, rgbInfoValue, cbInfoValueMax, pcbInfoValue _wide0));
    1061             : }
    1062             : 
    1063             : #ifdef ENABLE_ODBC_WIDE
    1064             : SQLRETURN ODBC_PUBLIC ODBC_API
    1065             : SQLGetInfoW(SQLHDBC hdbc, SQLUSMALLINT fInfoType, SQLPOINTER rgbInfoValue, SQLSMALLINT cbInfoValueMax,
    1066             :             SQLSMALLINT FAR *pcbInfoValue)
    1067             : {
    1068         473 :         ODBC_ENTER_HDBC;
    1069             : 
    1070         473 :         tdsdump_log(TDS_DBG_FUNC, "SQLGetInfoW(%p, %d, %p, %d, %p)\n", hdbc, fInfoType, rgbInfoValue, cbInfoValueMax, pcbInfoValue);
    1071             : 
    1072         473 :         ODBC_EXIT(dbc, odbc_SQLGetInfo(dbc, fInfoType, rgbInfoValue, cbInfoValueMax, pcbInfoValue, 1));
    1073             : }
    1074             : #endif

Generated by: LCOV version 1.13