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
|