1 /********************************************************************/
2 /* */
3 /* sql_cli.c Database access functions for ODBC/CLI interface. */
4 /* Copyright (C) 1989 - 2020 Thomas Mertes */
5 /* */
6 /* This file is part of the Seed7 Runtime Library. */
7 /* */
8 /* The Seed7 Runtime Library is free software; you can */
9 /* redistribute it and/or modify it under the terms of the GNU */
10 /* Lesser General Public License as published by the Free Software */
11 /* Foundation; either version 2.1 of the License, or (at your */
12 /* option) any later version. */
13 /* */
14 /* The Seed7 Runtime Library is distributed in the hope that it */
15 /* will be useful, but WITHOUT ANY WARRANTY; without even the */
16 /* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /* PURPOSE. See the GNU Lesser General Public License for more */
18 /* details. */
19 /* */
20 /* You should have received a copy of the GNU Lesser General */
21 /* Public License along with this program; if not, write to the */
22 /* Free Software Foundation, Inc., 51 Franklin Street, */
23 /* Fifth Floor, Boston, MA 02110-1301, USA. */
24 /* */
25 /* Module: Seed7 Runtime Library */
26 /* File: seed7/src/sql_cli.c */
27 /* Changes: 2014, 2015, 2017 - 2020 Thomas Mertes */
28 /* Content: Database access functions for ODBC/CLI interface. */
29 /* */
30 /********************************************************************/
31
32 typedef struct {
33 uintType usage_count;
34 sqlFuncType sqlFunc;
35 intType driver;
36 SQLHENV sql_environment;
37 SQLHDBC connection;
38 boolType wideCharsSupported;
39 boolType tinyintIsUnsigned;
40 SQLUSMALLINT maxConcurrentActivities;
41 } dbRecord, *dbType;
42
43 typedef struct {
44 int sql_type;
45 memSizeType buffer_length;
46 memSizeType buffer_capacity;
47 void *buffer;
48 SQLLEN length;
49 SQLSMALLINT dataType;
50 SQLULEN paramSize;
51 SQLSMALLINT decimalDigits;
52 SQLSMALLINT nullable;
53 boolType bound;
54 } bindDataRecord, *bindDataType;
55
56 typedef struct {
57 SQLSMALLINT c_type;
58 memSizeType buffer_length;
59 SQLSMALLINT dataType;
60 SQLULEN columnSize;
61 SQLSMALLINT decimalDigits;
62 SQLSMALLINT nullable;
63 boolType sql_data_at_exec;
64 } resultDescrRecord, *resultDescrType;
65
66 typedef struct {
67 void *buffer;
68 SQLLEN length;
69 } resultDataRecord, *resultDataType;
70
71
72 typedef struct fetchDataStruct *fetchDataType;
73
74 typedef struct fetchDataStruct {
75 resultDataType result_array;
76 SQLRETURN fetch_result;
77 fetchDataType next;
78 } fetchDataRecord;
79
80 typedef struct {
81 uintType usage_count;
82 sqlFuncType sqlFunc;
83 dbType db;
84 SQLHSTMT ppStmt;
85 memSizeType param_array_size;
86 bindDataType param_array;
87 memSizeType result_array_size;
88 resultDescrType result_descr_array;
89 fetchDataType prefetched;
90 fetchDataType currentFetch;
91 fetchDataRecord fetchRecord;
92 boolType hasBlob;
93 boolType executeSuccessful;
94 boolType fetchOkay;
95 boolType fetchFinished;
96 } preparedStmtRecord, *preparedStmtType;
97
98 static sqlFuncType sqlFunc = NULL;
99
100 /* ODBC provides two possibilities to encode decimal values. */
101 /* 1. As string of decimal digits. */
102 /* 2. As binary encoded data in the struct SQL_NUMERIC_STRUCT. */
103 /* Some databases provide decimal values beyond the capabilities of */
104 /* SQL_NUMERIC_STRUCT. Additionally SQL_NUMERIC_STRUCT values are */
105 /* not correctly supported by some drivers. Therefore decimal */
106 /* encoding is the default and encoding DECODE_NUMERIC_STRUCT */
107 /* should be used with care. */
108 #define DECODE_NUMERIC_STRUCT 0
109 #define ENCODE_NUMERIC_STRUCT 0
110 /* Maximum number of decimal digits that fits in in SQL_NUMERIC_STRUCT */
111 #define MAX_NUMERIC_PRECISION 38
112 #define MIN_PRECISION_FOR_NUMERIC_AS_DECIMAL 100
113 #define MAX_PRECISION_FOR_NUMERIC_AS_DECIMAL 1000
114 #define DEFAULT_DECIMAL_SCALE 1000
115 #define SQLLEN_MAX (SQLLEN) (((SQLULEN) 1 << (8 * sizeof(SQLLEN) - 1)) - 1)
116 #define SQLINTEGER_MAX (SQLINTEGER) (((SQLUINTEGER) 1 << (8 * sizeof(SQLINTEGER) - 1)) - 1)
117 #define SQLSMALLINT_MAX (SQLSMALLINT) (((SQLUSMALLINT) 1 << (8 * sizeof(SQLSMALLINT) - 1)) - 1)
118 #define ERROR_MESSAGE_BUFFER_SIZE 1000
119 #define MAX_DATETIME2_LENGTH 27
120 #define MAX_DURATION_LENGTH 32
121 #define CHARS_IN_NAME_BUFFER 256
122 #define MAX_WSTRI_TO_UTF8_EXPANSION_FACTOR 4
123
124 #ifndef SQL_BLOB
125 #define SQL_BLOB -98
126 #endif
127 #ifndef SQL_CLOB
128 #define SQL_CLOB -99
129 #endif
130 #ifndef SQL_SS_TIME2
131 #define SQL_SS_TIME2 -154
132 #endif
133 #ifndef SQL_XML
134 #define SQL_XML -370
135 #endif
136
137 typedef struct {
138 SQLUSMALLINT hour;
139 SQLUSMALLINT minute;
140 SQLUSMALLINT second;
141 SQLUINTEGER fraction;
142 } sqlSsTime2Struct;
143
144
145 /* Define formats for SQLLEN and SQLULEN */
146 #if POINTER_SIZE == 32
147 #define FMT_D_LEN FMT_D32
148 #define FMT_U_LEN FMT_U32
149 #elif POINTER_SIZE == 64
150 #define FMT_D_LEN FMT_D64
151 #define FMT_U_LEN FMT_U64
152 #endif
153
154
155 #ifdef CLI_DLL
156
157 #define FUNCTION_PRESENT(func) ((func) != NULL)
158
159 #ifndef STDCALL
160 #if defined(_WIN32) && HAS_STDCALL
161 #define STDCALL __stdcall
162 #else
163 #define STDCALL
164 #endif
165 #endif
166
167 typedef SQLRETURN (STDCALL *tp_SQLAllocHandle) (SQLSMALLINT handleType,
168 SQLHANDLE inputHandle,
169 SQLHANDLE *outputHandle);
170 typedef SQLRETURN (STDCALL *tp_SQLBindCol) (SQLHSTMT statementHandle,
171 SQLUSMALLINT columnNumber,
172 SQLSMALLINT targetType,
173 SQLPOINTER targetValue,
174 SQLLEN bufferLength,
175 SQLLEN *strLen_or_Ind);
176 typedef SQLRETURN (STDCALL *tp_SQLBindParameter) (SQLHSTMT hstmt,
177 SQLUSMALLINT ipar,
178 SQLSMALLINT fParamType,
179 SQLSMALLINT fCType,
180 SQLSMALLINT fSqlType,
181 SQLULEN cbColDef,
182 SQLSMALLINT ibScale,
183 SQLPOINTER rgbValue,
184 SQLLEN cbValueMax,
185 SQLLEN *pcbValue);
186 typedef SQLRETURN (STDCALL *tp_SQLBrowseConnectW) (SQLHDBC connectionHandle,
187 SQLWCHAR *inConnectionString,
188 SQLSMALLINT stringLength1,
189 SQLWCHAR *outConnectionString,
190 SQLSMALLINT bufferLength,
191 SQLSMALLINT *stringLength2Ptr);
192 typedef SQLRETURN (STDCALL *tp_SQLColAttributeW) (SQLHSTMT statementHandle,
193 SQLUSMALLINT columnNumber,
194 SQLUSMALLINT fieldIdentifier,
195 SQLPOINTER characterAttribute,
196 SQLSMALLINT bufferLength,
197 SQLSMALLINT *stringLengthPtr,
198 SQLLEN *numericAttribute);
199 typedef SQLRETURN (STDCALL *tp_SQLConnectW) (SQLHDBC connectionHandle,
200 SQLWCHAR *serverName,
201 SQLSMALLINT nameLength1,
202 SQLWCHAR *userName,
203 SQLSMALLINT nameLength2,
204 SQLWCHAR *authentication,
205 SQLSMALLINT nameLength3);
206 typedef SQLRETURN (STDCALL *tp_SQLDataSources) (SQLHENV environmentHandle,
207 SQLUSMALLINT direction,
208 SQLCHAR *serverName,
209 SQLSMALLINT bufferLength1,
210 SQLSMALLINT *nameLength1,
211 SQLCHAR *description,
212 SQLSMALLINT bufferLength2,
213 SQLSMALLINT *nameLength2);
214 typedef SQLRETURN (STDCALL *tp_SQLDescribeColW) (SQLHSTMT statementHandle,
215 SQLUSMALLINT columnNumber,
216 SQLWCHAR *columnName,
217 SQLSMALLINT bufferLength,
218 SQLSMALLINT *nameLengthPtr,
219 SQLSMALLINT *dataTypePtr,
220 SQLULEN *columnSizePtr,
221 SQLSMALLINT *decimalDigitsPtr,
222 SQLSMALLINT *nullablePtr);
223 typedef SQLRETURN (STDCALL *tp_SQLDescribeParam) (SQLHSTMT statementHandle,
224 SQLUSMALLINT parameterNumber,
225 SQLSMALLINT *dataTypePtr,
226 SQLULEN *parameterSizePtr,
227 SQLSMALLINT *decimalDigitsPtr,
228 SQLSMALLINT *nullablePtr);
229 typedef SQLRETURN (STDCALL *tp_SQLDisconnect) (SQLHDBC connectionHandle);
230 typedef SQLRETURN (STDCALL *tp_SQLDriverConnectW) (SQLHDBC connectionHandle,
231 SQLHWND windowHandle,
232 SQLWCHAR *inConnectionString,
233 SQLSMALLINT stringLength1,
234 SQLWCHAR *outConnectionString,
235 SQLSMALLINT bufferLength,
236 SQLSMALLINT *stringLength2Ptr,
237 SQLUSMALLINT driverCompletion);
238 typedef SQLRETURN (STDCALL *tp_SQLDriversW) (SQLHENV henv,
239 SQLUSMALLINT fDirection,
240 SQLWCHAR *szDriverDesc,
241 SQLSMALLINT cbDriverDescMax,
242 SQLSMALLINT *pcbDriverDesc,
243 SQLWCHAR *szDriverAttributes,
244 SQLSMALLINT cbDrvrAttrMax,
245 SQLSMALLINT *pcbDrvrAttr);
246 typedef SQLRETURN (STDCALL *tp_SQLEndTran) (SQLSMALLINT handleType,
247 SQLHANDLE handle,
248 SQLSMALLINT completionType);
249 typedef SQLRETURN (STDCALL *tp_SQLExecute) (SQLHSTMT statementHandle);
250 typedef SQLRETURN (STDCALL *tp_SQLFetch) (SQLHSTMT statementHandle);
251 typedef SQLRETURN (STDCALL *tp_SQLFreeHandle) (SQLSMALLINT handleType,
252 SQLHANDLE handle);
253 typedef SQLRETURN (STDCALL *tp_SQLFreeStmt) (SQLHSTMT statementHandle,
254 SQLUSMALLINT option);
255 typedef SQLRETURN (STDCALL *tp_SQLGetConnectAttrW) (SQLHDBC connectionHandle,
256 SQLINTEGER attribute,
257 SQLPOINTER valuePtr,
258 SQLINTEGER bufferLength,
259 SQLINTEGER *stringLengthPtr);
260 typedef SQLRETURN (STDCALL *tp_SQLGetData) (SQLHSTMT statementHandle,
261 SQLUSMALLINT columnNumber,
262 SQLSMALLINT targetType,
263 SQLPOINTER targetValue,
264 SQLLEN bufferLength,
265 SQLLEN *strLen_or_Ind);
266 typedef SQLRETURN (STDCALL *tp_SQLGetDiagRecW) (SQLSMALLINT handleType,
267 SQLHANDLE handle,
268 SQLSMALLINT recNumber,
269 SQLWCHAR *sqlstate,
270 SQLINTEGER *nativeError,
271 SQLWCHAR *messageText,
272 SQLSMALLINT bufferLength,
273 SQLSMALLINT *textLength);
274 typedef SQLRETURN (STDCALL *tp_SQLGetInfoW) (SQLHDBC connectionHandle,
275 SQLUSMALLINT infoType,
276 SQLPOINTER infoValuePtr,
277 SQLSMALLINT bufferLength,
278 SQLSMALLINT *stringLengthPtr);
279 typedef SQLRETURN (STDCALL *tp_SQLGetStmtAttrW) (SQLHSTMT statementHandle,
280 SQLINTEGER attribute,
281 SQLPOINTER value,
282 SQLINTEGER bufferLength,
283 SQLINTEGER *stringLength);
284 typedef SQLRETURN (STDCALL *tp_SQLGetTypeInfoW) (SQLHSTMT statementHandle,
285 SQLSMALLINT dataType);
286 typedef SQLRETURN (STDCALL *tp_SQLNumParams) (SQLHSTMT statementHandle,
287 SQLSMALLINT *parameterCountPtr);
288 typedef SQLRETURN (STDCALL *tp_SQLNumResultCols) (SQLHSTMT statementHandle,
289 SQLSMALLINT *columnCount);
290 typedef SQLRETURN (STDCALL *tp_SQLPrepareW) (SQLHSTMT statementHandle,
291 SQLWCHAR *statementText,
292 SQLINTEGER textLength);
293 typedef SQLRETURN (STDCALL *tp_SQLSetConnectAttrW) (SQLHDBC connectionHandle,
294 SQLINTEGER attribute,
295 SQLPOINTER valuePtr,
296 SQLINTEGER stringLength);
297 typedef SQLRETURN (STDCALL *tp_SQLSetDescFieldW) (SQLHDESC descriptorHandle,
298 SQLSMALLINT recNumber,
299 SQLSMALLINT fieldIdentifier,
300 SQLPOINTER value,
301 SQLINTEGER bufferLength);
302 typedef SQLRETURN (STDCALL *tp_SQLSetEnvAttr) (SQLHENV environmentHandle,
303 SQLINTEGER attribute,
304 SQLPOINTER value,
305 SQLINTEGER stringLength);
306
307 static tp_SQLAllocHandle ptr_SQLAllocHandle;
308 static tp_SQLBindCol ptr_SQLBindCol;
309 static tp_SQLBindParameter ptr_SQLBindParameter;
310 static tp_SQLBrowseConnectW ptr_SQLBrowseConnectW;
311 static tp_SQLColAttributeW ptr_SQLColAttributeW;
312 static tp_SQLConnectW ptr_SQLConnectW;
313 static tp_SQLDataSources ptr_SQLDataSources;
314 static tp_SQLDescribeColW ptr_SQLDescribeColW;
315 static tp_SQLDescribeParam ptr_SQLDescribeParam;
316 static tp_SQLDisconnect ptr_SQLDisconnect;
317 static tp_SQLDriverConnectW ptr_SQLDriverConnectW;
318 static tp_SQLDriversW ptr_SQLDriversW;
319 static tp_SQLEndTran ptr_SQLEndTran;
320 static tp_SQLExecute ptr_SQLExecute;
321 static tp_SQLFetch ptr_SQLFetch;
322 static tp_SQLFreeHandle ptr_SQLFreeHandle;
323 static tp_SQLFreeStmt ptr_SQLFreeStmt;
324 static tp_SQLGetConnectAttrW ptr_SQLGetConnectAttrW;
325 static tp_SQLGetData ptr_SQLGetData;
326 static tp_SQLGetDiagRecW ptr_SQLGetDiagRecW;
327 static tp_SQLGetInfoW ptr_SQLGetInfoW;
328 static tp_SQLGetStmtAttrW ptr_SQLGetStmtAttrW;
329 static tp_SQLGetTypeInfoW ptr_SQLGetTypeInfoW;
330 static tp_SQLNumParams ptr_SQLNumParams;
331 static tp_SQLNumResultCols ptr_SQLNumResultCols;
332 static tp_SQLPrepareW ptr_SQLPrepareW;
333 static tp_SQLSetConnectAttrW ptr_SQLSetConnectAttrW;
334 static tp_SQLSetDescFieldW ptr_SQLSetDescFieldW;
335 static tp_SQLSetEnvAttr ptr_SQLSetEnvAttr;
336
337 #define SQLAllocHandle ptr_SQLAllocHandle
338 #define SQLBindCol ptr_SQLBindCol
339 #define SQLBindParameter ptr_SQLBindParameter
340 #define SQLBrowseConnectW ptr_SQLBrowseConnectW
341 #define SQLColAttributeW ptr_SQLColAttributeW
342 #define SQLConnectW ptr_SQLConnectW
343 #define SQLDataSources ptr_SQLDataSources
344 #define SQLDescribeColW ptr_SQLDescribeColW
345 #define SQLDescribeParam ptr_SQLDescribeParam
346 #define SQLDisconnect ptr_SQLDisconnect
347 #define SQLDriverConnectW ptr_SQLDriverConnectW
348 #define SQLDriversW ptr_SQLDriversW
349 #define SQLEndTran ptr_SQLEndTran
350 #define SQLExecute ptr_SQLExecute
351 #define SQLFetch ptr_SQLFetch
352 #define SQLFreeHandle ptr_SQLFreeHandle
353 #define SQLFreeStmt ptr_SQLFreeStmt
354 #define SQLGetConnectAttrW ptr_SQLGetConnectAttrW
355 #define SQLGetData ptr_SQLGetData
356 #define SQLGetDiagRecW ptr_SQLGetDiagRecW
357 #define SQLGetInfoW ptr_SQLGetInfoW
358 #define SQLGetStmtAttrW ptr_SQLGetStmtAttrW
359 #define SQLGetTypeInfoW ptr_SQLGetTypeInfoW
360 #define SQLNumParams ptr_SQLNumParams
361 #define SQLNumResultCols ptr_SQLNumResultCols
362 #define SQLPrepareW ptr_SQLPrepareW
363 #define SQLSetConnectAttrW ptr_SQLSetConnectAttrW
364 #define SQLSetDescFieldW ptr_SQLSetDescFieldW
365 #define SQLSetEnvAttr ptr_SQLSetEnvAttr
366
367
368
setupDll(const char * dllName)369 static boolType setupDll (const char *dllName)
370
371 {
372 static void *dbDll = NULL;
373
374 /* setupDll */
375 logFunction(printf("setupDll(\"%s\")\n", dllName););
376 if (dbDll == NULL) {
377 dbDll = dllOpen(dllName);
378 if (dbDll != NULL) {
379 if ((SQLAllocHandle = (tp_SQLAllocHandle) dllFunc(dbDll, "SQLAllocHandle")) == NULL ||
380 (SQLBindCol = (tp_SQLBindCol) dllFunc(dbDll, "SQLBindCol")) == NULL ||
381 (SQLBindParameter = (tp_SQLBindParameter) dllFunc(dbDll, "SQLBindParameter")) == NULL ||
382 #ifdef ODBC_DRIVER_FUNCTIONS_NEEDED
383 (SQLBrowseConnectW = (tp_SQLBrowseConnectW) dllFunc(dbDll, "SQLBrowseConnectW")) == NULL ||
384 #else
385 (SQLBrowseConnectW = (tp_SQLBrowseConnectW) dllFunc(dbDll, "SQLBrowseConnectW"), FALSE) ||
386 #endif
387 (SQLColAttributeW = (tp_SQLColAttributeW) dllFunc(dbDll, "SQLColAttributeW")) == NULL ||
388 (SQLConnectW = (tp_SQLConnectW) dllFunc(dbDll, "SQLConnectW")) == NULL ||
389 #ifdef ODBC_DRIVER_FUNCTIONS_NEEDED
390 (SQLDataSources = (tp_SQLDataSources) dllFunc(dbDll, "SQLDataSources")) == NULL ||
391 #else
392 (SQLDataSources = (tp_SQLDataSources) NULL, FALSE) ||
393 #endif
394 (SQLDescribeColW = (tp_SQLDescribeColW) dllFunc(dbDll, "SQLDescribeColW")) == NULL ||
395 (SQLDescribeParam = (tp_SQLDescribeParam) dllFunc(dbDll, "SQLDescribeParam"), FALSE) ||
396 (SQLDisconnect = (tp_SQLDisconnect) dllFunc(dbDll, "SQLDisconnect")) == NULL ||
397 (SQLDriverConnectW = (tp_SQLDriverConnectW) dllFunc(dbDll, "SQLDriverConnectW")) == NULL ||
398 #ifdef ODBC_DRIVER_FUNCTIONS_NEEDED
399 (SQLDriversW = (tp_SQLDriversW) dllFunc(dbDll, "SQLDriversW")) == NULL ||
400 #else
401 (SQLDriversW = (tp_SQLDriversW) NULL, FALSE) ||
402 #endif
403 (SQLEndTran = (tp_SQLEndTran) dllFunc(dbDll, "SQLEndTran")) == NULL ||
404 (SQLExecute = (tp_SQLExecute) dllFunc(dbDll, "SQLExecute")) == NULL ||
405 (SQLFetch = (tp_SQLFetch) dllFunc(dbDll, "SQLFetch")) == NULL ||
406 (SQLFreeHandle = (tp_SQLFreeHandle) dllFunc(dbDll, "SQLFreeHandle")) == NULL ||
407 (SQLFreeStmt = (tp_SQLFreeStmt) dllFunc(dbDll, "SQLFreeStmt")) == NULL ||
408 (SQLGetConnectAttrW = (tp_SQLGetConnectAttrW) dllFunc(dbDll, "SQLGetConnectAttrW")) == NULL ||
409 (SQLGetData = (tp_SQLGetData) dllFunc(dbDll, "SQLGetData")) == NULL ||
410 (SQLGetDiagRecW = (tp_SQLGetDiagRecW) dllFunc(dbDll, "SQLGetDiagRecW")) == NULL ||
411 (SQLGetInfoW = (tp_SQLGetInfoW) dllFunc(dbDll, "SQLGetInfoW")) == NULL ||
412 (SQLGetStmtAttrW = (tp_SQLGetStmtAttrW) dllFunc(dbDll, "SQLGetStmtAttrW")) == NULL ||
413 (SQLGetTypeInfoW = (tp_SQLGetTypeInfoW) dllFunc(dbDll, "SQLGetTypeInfoW")) == NULL ||
414 (SQLNumParams = (tp_SQLNumParams ) dllFunc(dbDll, "SQLNumParams")) == NULL ||
415 (SQLNumResultCols = (tp_SQLNumResultCols) dllFunc(dbDll, "SQLNumResultCols")) == NULL ||
416 (SQLPrepareW = (tp_SQLPrepareW) dllFunc(dbDll, "SQLPrepareW")) == NULL ||
417 (SQLSetConnectAttrW = (tp_SQLSetConnectAttrW) dllFunc(dbDll, "SQLSetConnectAttrW")) == NULL ||
418 (SQLSetDescFieldW = (tp_SQLSetDescFieldW) dllFunc(dbDll, "SQLSetDescFieldW")) == NULL ||
419 (SQLSetEnvAttr = (tp_SQLSetEnvAttr) dllFunc(dbDll, "SQLSetEnvAttr")) == NULL) {
420 dbDll = NULL;
421 } /* if */
422 } /* if */
423 } /* if */
424 logFunction(printf("setupDll --> %d\n", dbDll != NULL););
425 return dbDll != NULL;
426 } /* setupDll */
427
428
429
findDll(void)430 static boolType findDll (void)
431
432 {
433 const char *dllList[] = { CLI_DLL };
434 unsigned int pos;
435 boolType found = FALSE;
436
437 /* findDll */
438 for (pos = 0; pos < sizeof(dllList) / sizeof(char *) && !found; pos++) {
439 found = setupDll(dllList[pos]);
440 } /* for */
441 if (!found) {
442 dllErrorMessage("sqlOpen", "findDll", dllList,
443 sizeof(dllList) / sizeof(char *));
444 } /* if */
445 return found;
446 } /* findDll */
447
448 #else
449
450 #define findDll() TRUE
451 #define FUNCTION_PRESENT(func) TRUE
452
453 #endif
454
455
456
457 static void sqlClose (databaseType database);
458
459
460
wstri_to_cstri8(ustriType cstri8,const_wstriType wstri)461 static void wstri_to_cstri8 (ustriType cstri8, const_wstriType wstri)
462
463 {
464 strElemType ch1;
465 wcharType ch2;
466
467 /* wstri_to_cstri8 */
468 for (; (ch1 = *wstri) != 0; wstri++) {
469 if (unlikely(ch1 >= 0xD800 && ch1 <= 0xDBFF)) {
470 ch2 = wstri[1];
471 if (likely(ch2 >= 0xDC00 && ch2 <= 0xDFFF)) {
472 ch1 = ((((strElemType) ch1 - 0xD800) << 10) +
473 ((strElemType) ch2 - 0xDC00) + 0x10000);
474 wstri++;
475 } /* if */
476 } /* if */
477 if (likely(ch1 != 0)) {
478 if (ch1 <= 0x7F) {
479 *cstri8++ = (ucharType) ch1;
480 } else if (ch1 <= 0x7FF) {
481 cstri8[0] = (ucharType) (0xC0 | (ch1 >> 6));
482 cstri8[1] = (ucharType) (0x80 |( ch1 & 0x3F));
483 cstri8 += 2;
484 } else if (ch1 <= 0xFFFF) {
485 cstri8[0] = (ucharType) (0xE0 | (ch1 >> 12));
486 cstri8[1] = (ucharType) (0x80 |((ch1 >> 6) & 0x3F));
487 cstri8[2] = (ucharType) (0x80 |( ch1 & 0x3F));
488 cstri8 += 3;
489 } else {
490 cstri8[0] = (ucharType) (0xF0 | (ch1 >> 18));
491 cstri8[1] = (ucharType) (0x80 |((ch1 >> 12) & 0x3F));
492 cstri8[2] = (ucharType) (0x80 |((ch1 >> 6) & 0x3F));
493 cstri8[3] = (ucharType) (0x80 |( ch1 & 0x3F));
494 cstri8 += 4;
495 } /* if */
496 } /* if */
497 } /* for */
498 *cstri8 = '\0';
499 } /* wstri_to_cstri8 */
500
501
502
setDbErrorMsg(const char * funcName,const char * dbFuncName,SQLSMALLINT handleType,SQLHANDLE handle)503 static void setDbErrorMsg (const char *funcName, const char *dbFuncName,
504 SQLSMALLINT handleType, SQLHANDLE handle)
505
506 {
507 SQLRETURN returnCode;
508 SQLWCHAR sqlState[5 + NULL_TERMINATION_LEN];
509 ucharType sqlState8[5 * MAX_WSTRI_TO_UTF8_EXPANSION_FACTOR + NULL_TERMINATION_LEN];
510 SQLWCHAR messageText[ERROR_MESSAGE_BUFFER_SIZE];
511 ucharType messageText8[ERROR_MESSAGE_BUFFER_SIZE * MAX_WSTRI_TO_UTF8_EXPANSION_FACTOR];
512 SQLINTEGER nativeError;
513 SQLSMALLINT bufferLength;
514
515 /* setDbErrorMsg */
516 dbError.funcName = funcName;
517 dbError.dbFuncName = dbFuncName;
518 returnCode = SQLGetDiagRecW(handleType,
519 handle,
520 1,
521 sqlState,
522 &nativeError,
523 messageText,
524 (SQLSMALLINT) ERROR_MESSAGE_BUFFER_SIZE,
525 &bufferLength);
526 if (returnCode == SQL_NO_DATA) {
527 dbError.errorCode = 0;
528 snprintf(dbError.message, DB_ERR_MESSAGE_SIZE,
529 " *** SQLGetDiagRecW returned: SQL_NO_DATA");
530 } else if (returnCode != SQL_SUCCESS &&
531 returnCode != SQL_SUCCESS_WITH_INFO) {
532 dbError.errorCode = 0;
533 snprintf(dbError.message, DB_ERR_MESSAGE_SIZE,
534 " *** SQLGetDiagRecW returned: %d\n", returnCode);
535 } else {
536 dbError.errorCode = (intType) nativeError;
537 wstri_to_cstri8(sqlState8, sqlState);
538 wstri_to_cstri8(messageText8, messageText);
539 snprintf(dbError.message, DB_ERR_MESSAGE_SIZE,
540 "%s\nSQLState: %s\nNativeError: %ld\n",
541 messageText8, sqlState8, (long int) nativeError);
542 } /* if */
543 } /* setDbErrorMsg */
544
545
546
547 /**
548 * Closes a database and frees the memory used by it.
549 */
freeDatabase(databaseType database)550 static void freeDatabase (databaseType database)
551
552 {
553 dbType db;
554
555 /* freeDatabase */
556 logFunction(printf("freeDatabase(" FMT_U_MEM ")\n",
557 (memSizeType) database););
558 sqlClose(database);
559 db = (dbType) database;
560 FREE_RECORD2(db, dbRecord, count.database, count.database_bytes);
561 logFunction(printf("freeDatabase -->\n"););
562 } /* freeDatabase */
563
564
565
freeFetchData(preparedStmtType preparedStmt,fetchDataType fetchData)566 static void freeFetchData (preparedStmtType preparedStmt, fetchDataType fetchData)
567
568 {
569 memSizeType pos;
570
571 /* freeFetchData */
572 if (fetchData->result_array != NULL) {
573 for (pos = 0; pos < preparedStmt->result_array_size; pos++) {
574 free(fetchData->result_array[pos].buffer);
575 } /* for */
576 FREE_TABLE(fetchData->result_array, resultDataRecord, preparedStmt->result_array_size);
577 } /* if */
578 } /* freeFetchData */
579
580
581
freeFetch(preparedStmtType preparedStmt,fetchDataType fetchData)582 static void freeFetch (preparedStmtType preparedStmt, fetchDataType fetchData)
583
584 { /* freeFetch */
585 freeFetchData(preparedStmt, fetchData);
586 FREE_RECORD2(fetchData, fetchDataRecord,
587 count.fetch_data, count.fetch_data_bytes);
588 } /* freeFetch */
589
590
591
freePrefetched(preparedStmtType preparedStmt)592 static void freePrefetched (preparedStmtType preparedStmt)
593
594 {
595 fetchDataType prefetched;
596 fetchDataType oldFetchData;
597
598 /* freePrefetched */
599 prefetched = preparedStmt->prefetched;
600 while (prefetched != NULL) {
601 oldFetchData = prefetched;
602 prefetched = prefetched->next;
603 freeFetch(preparedStmt, oldFetchData);
604 } /* while */
605 preparedStmt->prefetched = NULL;
606 } /* freePrefetched */
607
608
609
610 /**
611 * Closes a prepared statement and frees the memory used by it.
612 */
freePreparedStmt(sqlStmtType sqlStatement)613 static void freePreparedStmt (sqlStmtType sqlStatement)
614
615 {
616 preparedStmtType preparedStmt;
617 memSizeType pos;
618
619 /* freePreparedStmt */
620 logFunction(printf("freePreparedStmt(" FMT_U_MEM ")\n",
621 (memSizeType) sqlStatement););
622 preparedStmt = (preparedStmtType) sqlStatement;
623 if (preparedStmt->param_array != NULL) {
624 for (pos = 0; pos < preparedStmt->param_array_size; pos++) {
625 free(preparedStmt->param_array[pos].buffer);
626 } /* for */
627 FREE_TABLE(preparedStmt->param_array, bindDataRecord, preparedStmt->param_array_size);
628 } /* if */
629 if (preparedStmt->result_descr_array != NULL) {
630 FREE_TABLE(preparedStmt->result_descr_array, resultDataRecord, preparedStmt->result_array_size);
631 } /* if */
632 freePrefetched(preparedStmt);
633 freeFetchData(preparedStmt, &preparedStmt->fetchRecord);
634 if (preparedStmt->db->connection != SQL_NULL_HANDLE) {
635 if (preparedStmt->executeSuccessful) {
636 /* Ignore possible errors. */
637 SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE);
638 } /* if */
639 SQLFreeHandle(SQL_HANDLE_STMT, preparedStmt->ppStmt);
640 } /* if */
641 preparedStmt->db->usage_count--;
642 if (preparedStmt->db->usage_count == 0) {
643 /* printf("FREE " FMT_X_MEM "\n", (memSizeType) preparedStmt->db); */
644 freeDatabase((databaseType) preparedStmt->db);
645 } /* if */
646 FREE_RECORD2(preparedStmt, preparedStmtRecord,
647 count.prepared_stmt, count.prepared_stmt_bytes);
648 logFunction(printf("freePreparedStmt -->\n"););
649 } /* freePreparedStmt */
650
651
652
653 #if LOG_FUNCTIONS_EVERYWHERE || LOG_FUNCTIONS || VERBOSE_EXCEPTIONS_EVERYWHERE || VERBOSE_EXCEPTIONS
nameOfSqlType(SQLSMALLINT sql_type)654 static const char *nameOfSqlType (SQLSMALLINT sql_type)
655
656 {
657 static char buffer[50];
658 const char *typeName;
659
660 /* nameOfSqlType */
661 logFunction(printf("nameOfSqlType(%d)\n", sql_type););
662 switch (sql_type) {
663 case SQL_CHAR: typeName = "SQL_CHAR"; break;
664 case SQL_VARCHAR: typeName = "SQL_VARCHAR"; break;
665 case SQL_LONGVARCHAR: typeName = "SQL_LONGVARCHAR"; break;
666 case SQL_WCHAR: typeName = "SQL_WCHAR"; break;
667 case SQL_WVARCHAR: typeName = "SQL_WVARCHAR"; break;
668 case SQL_WLONGVARCHAR: typeName = "SQL_WLONGVARCHAR"; break;
669 case SQL_BIT: typeName = "SQL_BIT"; break;
670 case SQL_TINYINT: typeName = "SQL_TINYINT"; break;
671 case SQL_SMALLINT: typeName = "SQL_SMALLINT"; break;
672 case SQL_INTEGER: typeName = "SQL_INTEGER"; break;
673 case SQL_BIGINT: typeName = "SQL_BIGINT"; break;
674 case SQL_DECIMAL: typeName = "SQL_DECIMAL"; break;
675 case SQL_NUMERIC: typeName = "SQL_NUMERIC"; break;
676 case SQL_REAL: typeName = "SQL_REAL"; break;
677 case SQL_FLOAT: typeName = "SQL_FLOAT"; break;
678 case SQL_DOUBLE: typeName = "SQL_DOUBLE"; break;
679 case SQL_TYPE_DATE: typeName = "SQL_TYPE_DATE"; break;
680 case SQL_TYPE_TIME: typeName = "SQL_TYPE_TIME"; break;
681 case SQL_DATETIME: typeName = "SQL_DATETIME"; break;
682 case SQL_TYPE_TIMESTAMP: typeName = "SQL_TYPE_TIMESTAMP"; break;
683 case SQL_INTERVAL_YEAR: typeName = "SQL_INTERVAL_YEAR"; break;
684 case SQL_INTERVAL_MONTH: typeName = "SQL_INTERVAL_MONTH"; break;
685 case SQL_INTERVAL_DAY: typeName = "SQL_INTERVAL_DAY"; break;
686 case SQL_INTERVAL_HOUR: typeName = "SQL_INTERVAL_HOUR"; break;
687 case SQL_INTERVAL_MINUTE: typeName = "SQL_INTERVAL_MINUTE"; break;
688 case SQL_INTERVAL_SECOND: typeName = "SQL_INTERVAL_SECOND"; break;
689 case SQL_INTERVAL_YEAR_TO_MONTH: typeName = "SQL_INTERVAL_YEAR_TO_MONTH"; break;
690 case SQL_INTERVAL_DAY_TO_HOUR: typeName = "SQL_INTERVAL_DAY_TO_HOUR"; break;
691 case SQL_INTERVAL_DAY_TO_MINUTE: typeName = "SQL_INTERVAL_DAY_TO_MINUTE"; break;
692 case SQL_INTERVAL_DAY_TO_SECOND: typeName = "SQL_INTERVAL_DAY_TO_SECOND"; break;
693 case SQL_INTERVAL_HOUR_TO_MINUTE: typeName = "SQL_INTERVAL_HOUR_TO_MINUTE"; break;
694 case SQL_INTERVAL_HOUR_TO_SECOND: typeName = "SQL_INTERVAL_HOUR_TO_SECOND"; break;
695 case SQL_INTERVAL_MINUTE_TO_SECOND: typeName = "SQL_INTERVAL_MINUTE_TO_SECOND"; break;
696 case SQL_BINARY: typeName = "SQL_BINARY"; break;
697 case SQL_VARBINARY: typeName = "SQL_VARBINARY"; break;
698 case SQL_LONGVARBINARY: typeName = "SQL_LONGVARBINARY"; break;
699 case SQL_SS_TIME2: typeName = "SQL_SS_TIME2"; break;
700 default:
701 sprintf(buffer, FMT_D16, sql_type);
702 typeName = buffer;
703 break;
704 } /* switch */
705 logFunction(printf("nameOfSqlType --> %s\n", typeName););
706 return typeName;
707 } /* nameOfSqlType */
708
709
710
nameOfCType(int c_type)711 static const char *nameOfCType (int c_type)
712
713 {
714 static char buffer[50];
715 const char *typeName;
716
717 /* nameOfCType */
718 switch (c_type) {
719 case SQL_C_CHAR: typeName = "SQL_C_CHAR"; break;
720 case SQL_C_WCHAR: typeName = "SQL_C_WCHAR"; break;
721 case SQL_C_BIT: typeName = "SQL_C_BIT"; break;
722 case SQL_C_STINYINT: typeName = "SQL_C_STINYINT"; break;
723 case SQL_C_UTINYINT: typeName = "SQL_C_UTINYINT"; break;
724 case SQL_C_SSHORT: typeName = "SQL_C_SSHORT"; break;
725 case SQL_C_SLONG: typeName = "SQL_C_SLONG"; break;
726 case SQL_C_SBIGINT: typeName = "SQL_C_SBIGINT"; break;
727 case SQL_C_NUMERIC: typeName = "SQL_C_NUMERIC"; break;
728 case SQL_C_FLOAT: typeName = "SQL_C_FLOAT"; break;
729 case SQL_C_DOUBLE: typeName = "SQL_C_DOUBLE"; break;
730 case SQL_C_TYPE_DATE: typeName = "SQL_C_TYPE_DATE"; break;
731 case SQL_C_TYPE_TIME: typeName = "SQL_C_TYPE_TIME"; break;
732 case SQL_C_TYPE_TIMESTAMP: typeName = "SQL_C_TYPE_TIMESTAMP"; break;
733 case SQL_C_INTERVAL_YEAR: typeName = "SQL_C_INTERVAL_YEAR"; break;
734 case SQL_C_INTERVAL_MONTH: typeName = "SQL_C_INTERVAL_MONTH"; break;
735 case SQL_C_INTERVAL_DAY: typeName = "SQL_C_INTERVAL_DAY"; break;
736 case SQL_C_INTERVAL_HOUR: typeName = "SQL_C_INTERVAL_HOUR"; break;
737 case SQL_C_INTERVAL_MINUTE: typeName = "SQL_C_INTERVAL_MINUTE"; break;
738 case SQL_C_INTERVAL_SECOND: typeName = "SQL_C_INTERVAL_SECOND"; break;
739 case SQL_C_INTERVAL_YEAR_TO_MONTH: typeName = "SQL_C_INTERVAL_YEAR_TO_MONTH"; break;
740 case SQL_C_INTERVAL_DAY_TO_HOUR: typeName = "SQL_C_INTERVAL_DAY_TO_HOUR"; break;
741 case SQL_C_INTERVAL_DAY_TO_MINUTE: typeName = "SQL_C_INTERVAL_DAY_TO_MINUTE"; break;
742 case SQL_C_INTERVAL_DAY_TO_SECOND: typeName = "SQL_C_INTERVAL_DAY_TO_SECOND"; break;
743 case SQL_C_INTERVAL_HOUR_TO_MINUTE: typeName = "SQL_C_INTERVAL_HOUR_TO_MINUTE"; break;
744 case SQL_C_INTERVAL_HOUR_TO_SECOND: typeName = "SQL_C_INTERVAL_HOUR_TO_SECOND"; break;
745 case SQL_C_INTERVAL_MINUTE_TO_SECOND: typeName = "SQL_C_INTERVAL_MINUTE_TO_SECOND"; break;
746 case SQL_C_BINARY: typeName = "SQL_C_BINARY"; break;
747 default:
748 sprintf(buffer, "%d", c_type);
749 typeName = buffer;
750 break;
751 } /* switch */
752 return typeName;
753 } /* nameOfCType */
754 #endif
755
756
757
758 /**
759 * Remove comments from the statement string.
760 * This avoids problems with some ODBC drivers.
761 * Some ODBC drivers do not remove comments so question marks (?)
762 * or quotes (') in comments are misinterpreted.
763 * String literals are scanned also to avoid that a comment
764 * inside a literal is removed.
765 */
processStatementStri(const const_striType sqlStatementStri,errInfoType * err_info)766 static striType processStatementStri (const const_striType sqlStatementStri,
767 errInfoType *err_info)
768
769 {
770 memSizeType pos = 0;
771 strElemType ch;
772 strElemType delimiter;
773 memSizeType destPos = 0;
774 striType processed;
775
776 /* processStatementStri */
777 logFunction(printf("processStatementStri(\"%s\")\n",
778 striAsUnquotedCStri(sqlStatementStri)););
779 if (unlikely(sqlStatementStri->size > MAX_STRI_LEN ||
780 !ALLOC_STRI_SIZE_OK(processed, sqlStatementStri->size))) {
781 *err_info = MEMORY_ERROR;
782 processed = NULL;
783 } else {
784 while (pos < sqlStatementStri->size && *err_info == OKAY_NO_ERROR) {
785 ch = sqlStatementStri->mem[pos];
786 if (ch == '\'' || ch == '"') {
787 delimiter = ch;
788 processed->mem[destPos++] = delimiter;
789 pos++;
790 while (pos < sqlStatementStri->size &&
791 (ch = sqlStatementStri->mem[pos]) != delimiter) {
792 processed->mem[destPos++] = ch;
793 pos++;
794 } /* while */
795 if (pos < sqlStatementStri->size) {
796 processed->mem[destPos++] = delimiter;
797 pos++;
798 } /* if */
799 } else if (ch == '/') {
800 pos++;
801 if (pos >= sqlStatementStri->size || sqlStatementStri->mem[pos] != '*') {
802 processed->mem[destPos++] = ch;
803 } else {
804 pos++;
805 do {
806 while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '*') {
807 pos++;
808 } /* while */
809 pos++;
810 } while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '/');
811 pos++;
812 /* Replace the comment with a space. */
813 processed->mem[destPos++] = ' ';
814 } /* if */
815 } else if (ch == '-') {
816 pos++;
817 if (pos >= sqlStatementStri->size || sqlStatementStri->mem[pos] != '-') {
818 processed->mem[destPos++] = ch;
819 } else {
820 pos++;
821 while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '\n') {
822 pos++;
823 } /* while */
824 /* The final newline replaces the comment. */
825 } /* if */
826 } else {
827 processed->mem[destPos++] = ch;
828 pos++;
829 } /* if */
830 } /* while */
831 processed->size = destPos;
832 } /* if */
833 logFunction(printf("processStatementStri --> \"%s\"\n",
834 striAsUnquotedCStri(processed)););
835 return processed;
836 } /* processStatementStri */
837
838
839
hasDataType(SQLHDBC connection,SQLSMALLINT requestedDataType,errInfoType * err_info)840 static boolType hasDataType (SQLHDBC connection, SQLSMALLINT requestedDataType,
841 errInfoType *err_info)
842
843 {
844 SQLHSTMT ppStmt;
845 SQLRETURN returnCode;
846 boolType hasType = FALSE;
847
848 /* hasDataType */
849 logFunction(printf("hasDataType(*, " FMT_D16 ", *)\n", requestedDataType););
850 if (SQLAllocHandle(SQL_HANDLE_STMT,
851 connection,
852 &ppStmt) != SQL_SUCCESS) {
853 setDbErrorMsg("hasDataType", "SQLAllocHandle",
854 SQL_HANDLE_DBC, connection);
855 logError(printf("hasDataType: SQLAllocHandle SQL_HANDLE_STMT:\n%s\n",
856 dbError.message););
857 *err_info = DATABASE_ERROR;
858 } else {
859 returnCode = SQLGetTypeInfoW(ppStmt, requestedDataType);
860 /* printf("returnCode: " FMT_D16 "\n", returnCode); */
861 if (returnCode == SQL_SUCCESS) {
862 if (SQLFetch(ppStmt) == SQL_SUCCESS) {
863 hasType = TRUE;
864 } /* if */
865 } /* if */
866 SQLFreeHandle(SQL_HANDLE_STMT, ppStmt);
867 } /* if */
868 logFunction(printf("hasDataType --> %d\n", hasType););
869 return hasType;
870 } /* hasDataType */
871
872
873
dataTypeIsUnsigned(SQLHDBC connection,SQLSMALLINT requestedDataType,errInfoType * err_info)874 static boolType dataTypeIsUnsigned (SQLHDBC connection, SQLSMALLINT requestedDataType,
875 errInfoType *err_info)
876
877 {
878 SQLHSTMT ppStmt;
879 SQLRETURN returnCode;
880 SQLSMALLINT unsignedAttribute;
881 SQLLEN unsignedAttribute_ind;
882 SQLRETURN fetchResult;
883 boolType isUnsigned = FALSE;
884
885 /* dataTypeIsUnsigned */
886 logFunction(printf("dataTypeIsUnsigned(*, " FMT_D16 ", *)\n", requestedDataType););
887 if (SQLAllocHandle(SQL_HANDLE_STMT,
888 connection,
889 &ppStmt) != SQL_SUCCESS) {
890 setDbErrorMsg("dataTypeIsUnsigned", "SQLAllocHandle",
891 SQL_HANDLE_DBC, connection);
892 logError(printf("dataTypeIsUnsigned: SQLAllocHandle SQL_HANDLE_STMT:\n%s\n",
893 dbError.message););
894 *err_info = DATABASE_ERROR;
895 } else {
896 returnCode = SQLGetTypeInfoW(ppStmt, requestedDataType);
897 /* printf("returnCode: " FMT_D16 "\n", returnCode); */
898 if (returnCode != SQL_SUCCESS) {
899 setDbErrorMsg("dataTypeIsUnsigned", "SQLGetTypeInfoW",
900 SQL_HANDLE_DBC, connection);
901 logError(printf("dataTypeIsUnsigned: SQLGetTypeInfoW error:\n%s\n",
902 dbError.message););
903 *err_info = DATABASE_ERROR;
904 } else if (SQLBindCol(ppStmt,
905 10,
906 SQL_C_SHORT,
907 (SQLPOINTER) &unsignedAttribute,
908 (SQLLEN) sizeof(unsignedAttribute),
909 &unsignedAttribute_ind) != SQL_SUCCESS) {
910 setDbErrorMsg("dataTypeIsUnsigned", "SQLBindCol",
911 SQL_HANDLE_DBC, connection);
912 logError(printf("dataTypeIsUnsigned: SQLBindCol error:\n%s\n",
913 dbError.message););
914 *err_info = DATABASE_ERROR;
915 } else {
916 fetchResult = SQLFetch(ppStmt);
917 if (fetchResult == SQL_SUCCESS) {
918 if (unsignedAttribute_ind == SQL_NULL_DATA) {
919 logError(printf("dataTypeIsUnsigned: UNSIGNED_ATTRIBUTE is NULL.\n"););
920 *err_info = RANGE_ERROR;
921 } else {
922 isUnsigned = unsignedAttribute;
923 } /* if */
924 } else if (fetchResult == SQL_NO_DATA) {
925 /* No data found. Probably the dataType is not used at all. */
926 /* Assume that the dataType is signed. */
927 } else {
928 setDbErrorMsg("dataTypeIsUnsigned", "SQLFetch",
929 SQL_HANDLE_DBC, connection);
930 logError(printf("dataTypeIsUnsigned: SQLFetch error:\n%s\n",
931 dbError.message););
932 *err_info = DATABASE_ERROR;
933 } /* if */
934 } /* if */
935 SQLFreeHandle(SQL_HANDLE_STMT, ppStmt);
936 } /* if */
937 logFunction(printf("dataTypeIsUnsigned --> %d\n", isUnsigned););
938 return isUnsigned;
939 } /* dataTypeIsUnsigned */
940
941
942
setupParameterColumn(preparedStmtType preparedStmt,SQLUSMALLINT param_index,bindDataType param)943 static errInfoType setupParameterColumn (preparedStmtType preparedStmt,
944 SQLUSMALLINT param_index, bindDataType param)
945
946 {
947 errInfoType err_info = OKAY_NO_ERROR;
948
949 /* setupParameterColumn */
950 logFunction(printf("setupParameterColumn(*, " FMT_U16 ", *)\n",
951 param_index););
952 if (!FUNCTION_PRESENT(SQLDescribeParam) ||
953 SQLDescribeParam(preparedStmt->ppStmt,
954 (SQLUSMALLINT) (param_index + 1),
955 ¶m->dataType,
956 ¶m->paramSize,
957 ¶m->decimalDigits,
958 ¶m->nullable) != SQL_SUCCESS) {
959 /* The function SQLDescribeParam() of the MySQL driver for */
960 /* Unixodbc returns the values below. This are reasonable */
961 /* defaults, if the ODBC driver does not support the */
962 /* function SQLDescribeParam(). */
963 /* printf("FUNCTION_PRESENT(SQLDescribeParam): %d\n",
964 FUNCTION_PRESENT(SQLDescribeParam)); */
965 param->dataType = SQL_VARCHAR;
966 param->paramSize = 255;
967 param->decimalDigits = 0;
968 param->nullable = 1;
969 } /* if */
970 if (likely(err_info == OKAY_NO_ERROR)) {
971 /* printf("parameter: " FMT_U16 ", dataType: " FMT_D16 ", paramSize: " FMT_U_MEM
972 ", decimalDigits: " FMT_D16 "\n", param_index + 1,
973 param->dataType, param->paramSize, param->decimalDigits); */
974 switch (param->dataType) {
975 case SQL_BIT:
976 param->buffer_length = sizeof(char);
977 break;
978 case SQL_TINYINT:
979 param->buffer_length = sizeof(int8Type);
980 break;
981 case SQL_SMALLINT:
982 param->buffer_length = sizeof(int16Type);
983 break;
984 case SQL_INTEGER:
985 param->buffer_length = sizeof(int32Type);
986 break;
987 case SQL_BIGINT:
988 param->buffer_length = sizeof(int64Type);
989 break;
990 case SQL_REAL:
991 param->buffer_length = sizeof(float);
992 break;
993 case SQL_FLOAT:
994 case SQL_DOUBLE:
995 param->buffer_length = sizeof(double);
996 break;
997 case SQL_TYPE_DATE:
998 param->buffer_length = sizeof(SQL_DATE_STRUCT);
999 break;
1000 case SQL_TYPE_TIME:
1001 param->buffer_length = sizeof(SQL_TIME_STRUCT);
1002 break;
1003 case SQL_DATETIME:
1004 case SQL_TYPE_TIMESTAMP:
1005 param->buffer_length = sizeof(SQL_TIMESTAMP_STRUCT);
1006 break;
1007 case SQL_DECIMAL:
1008 case SQL_NUMERIC:
1009 case SQL_CHAR:
1010 case SQL_VARCHAR:
1011 case SQL_LONGVARCHAR:
1012 case SQL_WCHAR:
1013 case SQL_WVARCHAR:
1014 case SQL_WLONGVARCHAR:
1015 case SQL_BINARY:
1016 case SQL_VARBINARY:
1017 case SQL_LONGVARBINARY:
1018 case SQL_BLOB:
1019 case SQL_CLOB:
1020 /* For this data types no buffer is reserved. Therefore */
1021 /* param->buffer is NULL and param->buffer_capacity is 0. */
1022 /* All bind functions dealing with this data types check */
1023 /* the buffer_capacity and (re)allocate the buffer, if */
1024 /* necessary. */
1025 break;
1026 } /* switch */
1027 if (param->buffer_length != 0) {
1028 param->buffer = malloc(param->buffer_length);
1029 if (unlikely(param->buffer == NULL)) {
1030 param->buffer_length = 0;
1031 err_info = MEMORY_ERROR;
1032 } else {
1033 param->buffer_capacity = param->buffer_length;
1034 } /* if */
1035 } /* if */
1036 } /* if */
1037 logFunction(printf("setupParameterColumn --> %d\n", err_info););
1038 return err_info;
1039 } /* setupParameterColumn */
1040
1041
1042
setupParameters(preparedStmtType preparedStmt)1043 static errInfoType setupParameters (preparedStmtType preparedStmt)
1044
1045 {
1046 SQLSMALLINT num_params;
1047 SQLUSMALLINT param_index;
1048 errInfoType err_info = OKAY_NO_ERROR;
1049
1050 /* setupParameters */
1051 logFunction(printf("setupParameters\n"););
1052 if (SQLNumParams(preparedStmt->ppStmt,
1053 &num_params) != SQL_SUCCESS) {
1054 setDbErrorMsg("setupParameters", "SQLNumParams",
1055 SQL_HANDLE_STMT, preparedStmt->ppStmt);
1056 logError(printf("setupParameters: SQLNumParams:\n%s\n",
1057 dbError.message););
1058 err_info = DATABASE_ERROR;
1059 } else if (unlikely(num_params < 0)) {
1060 dbInconsistent("setupParameters", "SQLNumParams");
1061 logError(printf("setupParameters: SQLNumParams returns negative number: %hd\n",
1062 num_params););
1063 err_info = DATABASE_ERROR;
1064 } else if (num_params == 0) {
1065 /* malloc(0) may return NULL, which would wrongly trigger a MEMORY_ERROR. */
1066 preparedStmt->param_array_size = 0;
1067 preparedStmt->param_array = NULL;
1068 } else if (unlikely(!ALLOC_TABLE(preparedStmt->param_array,
1069 bindDataRecord, (memSizeType) num_params))) {
1070 err_info = MEMORY_ERROR;
1071 } else {
1072 preparedStmt->param_array_size = (memSizeType) num_params;
1073 memset(preparedStmt->param_array, 0,
1074 (memSizeType) num_params * sizeof(bindDataRecord));
1075 for (param_index = 0; param_index < num_params &&
1076 err_info == OKAY_NO_ERROR; param_index++) {
1077 err_info = setupParameterColumn(preparedStmt, param_index,
1078 &preparedStmt->param_array[param_index]);
1079 } /* for */
1080 } /* if */
1081 logFunction(printf("setupParameters --> %d\n", err_info););
1082 return err_info;
1083 } /* setupParameters */
1084
1085
1086
1087 #if DECODE_NUMERIC_STRUCT
1088 /**
1089 * Set precision and scale of SQL_C_NUMERIC data.
1090 * Otherwise the driver defined default precision and scale would be used.
1091 * This function is used for bound and unbound SQL_C_NUMERIC data.
1092 * If the function is used for bound data the data pointer
1093 * (SQL_DESC_DATA_PTR) must be set afterwards, because according
1094 * to the the documentation of SQLSetDescFieldW changes of the
1095 * attributes sets SQL_DESC_DATA_PTR to a NULL pointer.
1096 * If the function is used for unbound data setting the type is
1097 * necessary and setting the data pointer is omitted.
1098 */
setNumericPrecisionAndScale(preparedStmtType preparedStmt,SQLSMALLINT column_num,resultDescrType columnDescr,resultDataType columnData,boolType withBinding)1099 static errInfoType setNumericPrecisionAndScale (preparedStmtType preparedStmt,
1100 SQLSMALLINT column_num, resultDescrType columnDescr,
1101 resultDataType columnData, boolType withBinding)
1102 {
1103 SQLHDESC descriptorHandle;
1104 errInfoType err_info = OKAY_NO_ERROR;
1105
1106 /* setNumericPrecisionAndScale */
1107 /* printf("SQL_C_NUMERIC:\n");
1108 printf("columnSize: " FMT_U_MEM "\n", columnDescr->columnSize);
1109 printf("decimalDigits:" FMT_D16 "\n", columnDescr->decimalDigits);
1110 printf("buffer_length: " FMT_U_MEM "\n", columnDescr->buffer_length); */
1111 if (SQLGetStmtAttrW(preparedStmt->ppStmt,
1112 SQL_ATTR_APP_ROW_DESC,
1113 &descriptorHandle,
1114 0, NULL) != SQL_SUCCESS) {
1115 setDbErrorMsg("setNumericPrecisionAndScale", "SQLGetStmtAttrW",
1116 SQL_HANDLE_STMT, preparedStmt->ppStmt);
1117 logError(printf("setNumericPrecisionAndScale: SQLGetStmtAttrW "
1118 "SQL_ATTR_APP_ROW_DESC:\n%s\n",
1119 dbError.message););
1120 err_info = DATABASE_ERROR;
1121 } else if (!withBinding &&
1122 SQLSetDescFieldW(descriptorHandle,
1123 column_num,
1124 SQL_DESC_TYPE,
1125 (SQLPOINTER) SQL_C_NUMERIC,
1126 0) != SQL_SUCCESS) {
1127 setDbErrorMsg("setNumericPrecisionAndScale", "SQLSetDescFieldW",
1128 SQL_HANDLE_DESC, descriptorHandle);
1129 logError(printf("setNumericPrecisionAndScale: SQLSetDescFieldW "
1130 "SQL_DESC_TYPE:\n%s\n",
1131 dbError.message););
1132 err_info = DATABASE_ERROR;
1133 } else if (SQLSetDescFieldW(descriptorHandle,
1134 column_num,
1135 SQL_DESC_PRECISION,
1136 (SQLPOINTER) columnDescr->columnSize,
1137 0) != SQL_SUCCESS) {
1138 setDbErrorMsg("setNumericPrecisionAndScale", "SQLSetDescFieldW",
1139 SQL_HANDLE_DESC, descriptorHandle);
1140 logError(printf("setNumericPrecisionAndScale: SQLSetDescFieldW "
1141 "SQL_DESC_PRECISION:\n%s\n",
1142 dbError.message););
1143 err_info = DATABASE_ERROR;
1144 } else if (SQLSetDescFieldW(descriptorHandle,
1145 column_num,
1146 SQL_DESC_SCALE,
1147 (SQLPOINTER) (memSizeType) columnDescr->decimalDigits,
1148 0) != SQL_SUCCESS) {
1149 setDbErrorMsg("setNumericPrecisionAndScale", "SQLSetDescFieldW",
1150 SQL_HANDLE_DESC, descriptorHandle);
1151 logError(printf("setNumericPrecisionAndScale: SQLSetDescFieldW "
1152 "SQL_DESC_SCALE:\n%s\n",
1153 dbError.message););
1154 err_info = DATABASE_ERROR;
1155 } else if (withBinding &&
1156 SQLSetDescFieldW(descriptorHandle,
1157 column_num,
1158 SQL_DESC_DATA_PTR,
1159 columnData->buffer,
1160 0) != SQL_SUCCESS) {
1161 setDbErrorMsg("setNumericPrecisionAndScale", "SQLSetDescFieldW",
1162 SQL_HANDLE_DESC, descriptorHandle);
1163 logError(printf("setNumericPrecisionAndScale: SQLSetDescFieldW "
1164 "SQL_DESC_DATA_PTR:\n%s\n",
1165 dbError.message););
1166 err_info = DATABASE_ERROR;
1167 } /* if */
1168 return err_info;
1169 } /* setNumericPrecisionAndScale */
1170 #endif
1171
1172
1173
setupResultColumn(preparedStmtType preparedStmt,SQLSMALLINT column_num,resultDescrType columnDescr)1174 static errInfoType setupResultColumn (preparedStmtType preparedStmt,
1175 SQLSMALLINT column_num, resultDescrType columnDescr)
1176
1177 {
1178 SQLRETURN returnCode;
1179 SQLSMALLINT nameLength;
1180 SQLSMALLINT c_type;
1181 memSizeType buffer_length;
1182 errInfoType err_info = OKAY_NO_ERROR;
1183
1184 /* setupResultColumn */
1185 logFunction(printf("setupResultColumn: column_num=%d\n", column_num););
1186 returnCode = SQLDescribeColW(preparedStmt->ppStmt,
1187 (SQLUSMALLINT) column_num,
1188 NULL,
1189 0,
1190 &nameLength,
1191 &columnDescr->dataType,
1192 &columnDescr->columnSize,
1193 &columnDescr->decimalDigits,
1194 &columnDescr->nullable);
1195 if (unlikely(returnCode != SQL_SUCCESS &&
1196 returnCode != SQL_SUCCESS_WITH_INFO)) {
1197 setDbErrorMsg("setupResultColumn", "SQLDescribeColW",
1198 SQL_HANDLE_STMT, preparedStmt->ppStmt);
1199 logError(printf("setupResultColumn: SQLDescribeColW returns "
1200 FMT_D16 ":\n%s\n", returnCode, dbError.message););
1201 err_info = DATABASE_ERROR;
1202 } else {
1203 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
1204 switch (columnDescr->dataType) {
1205 case SQL_CHAR:
1206 case SQL_VARCHAR:
1207 if (preparedStmt->db->wideCharsSupported) {
1208 c_type = SQL_C_WCHAR;
1209 } else {
1210 c_type = SQL_C_CHAR;
1211 } /* if */
1212 if (unlikely(columnDescr->columnSize > (MAX_MEMSIZETYPE / 2) - 1)) {
1213 logError(printf("setupResultColumn: ColumnSize too big: " FMT_U_LEN "\n",
1214 columnDescr->columnSize););
1215 err_info = MEMORY_ERROR;
1216 } else {
1217 buffer_length = ((memSizeType) columnDescr->columnSize + 1) * 2;
1218 } /* if */
1219 /* printf("%s:\n", nameOfSqlType(columnDescr->dataType));
1220 printf("columnSize: " FMT_U_MEM "\n", columnDescr->columnSize);
1221 printf("SQLLEN_MAX: %ld\n", SQLLEN_MAX);
1222 printf("buffer_length: " FMT_U_MEM "\n", buffer_length);
1223 printf("decimalDigits: " FMT_D16 "\n", columnDescr->decimalDigits); */
1224 break;
1225 case SQL_WCHAR:
1226 case SQL_WVARCHAR:
1227 c_type = SQL_C_WCHAR;
1228 if (unlikely(columnDescr->columnSize > (MAX_MEMSIZETYPE / 2) - 1)) {
1229 logError(printf("setupResultColumn: ColumnSize too big: " FMT_U_LEN "\n",
1230 columnDescr->columnSize););
1231 err_info = MEMORY_ERROR;
1232 } else {
1233 buffer_length = ((memSizeType) columnDescr->columnSize + 1) * 2;
1234 } /* if */
1235 /* printf("%s:\n", nameOfSqlType(columnDescr->dataType));
1236 printf("columnSize: " FMT_U_MEM "\n", columnDescr->columnSize);
1237 printf("SQLLEN_MAX: %ld\n", SQLLEN_MAX);
1238 printf("buffer_length: " FMT_U_MEM "\n", buffer_length);
1239 printf("decimalDigits: " FMT_D16 "\n", columnDescr->decimalDigits); */
1240 break;
1241 case SQL_BINARY:
1242 case SQL_VARBINARY:
1243 c_type = SQL_C_BINARY;
1244 if (unlikely(columnDescr->columnSize > MAX_MEMSIZETYPE)) {
1245 logError(printf("setupResultColumn: ColumnSize too big: " FMT_U_LEN "\n",
1246 columnDescr->columnSize););
1247 err_info = MEMORY_ERROR;
1248 } else {
1249 buffer_length = (memSizeType) columnDescr->columnSize;
1250 } /* if */
1251 /* printf("%s:\n", nameOfSqlType(columnDescr->dataType));
1252 printf("columnSize: " FMT_U_MEM "\n", columnDescr->columnSize);
1253 printf("SQLLEN_MAX: %ld\n", SQLLEN_MAX);
1254 printf("buffer_length: " FMT_U_MEM "\n", buffer_length);
1255 printf("decimalDigits: " FMT_D16 "\n", columnDescr->decimalDigits); */
1256 break;
1257 case SQL_LONGVARCHAR:
1258 if (preparedStmt->db->wideCharsSupported) {
1259 c_type = SQL_C_WCHAR;
1260 } else {
1261 c_type = SQL_C_CHAR;
1262 } /* if */
1263 columnDescr->sql_data_at_exec = TRUE;
1264 buffer_length = (memSizeType) SQL_DATA_AT_EXEC;
1265 break;
1266 case SQL_WLONGVARCHAR:
1267 c_type = SQL_C_WCHAR;
1268 columnDescr->sql_data_at_exec = TRUE;
1269 buffer_length = (memSizeType) SQL_DATA_AT_EXEC;
1270 break;
1271 case SQL_LONGVARBINARY:
1272 c_type = SQL_C_BINARY;
1273 columnDescr->sql_data_at_exec = TRUE;
1274 buffer_length = (memSizeType) SQL_DATA_AT_EXEC;
1275 break;
1276 case SQL_BIT:
1277 c_type = SQL_C_BIT;
1278 buffer_length = sizeof(char);
1279 break;
1280 case SQL_TINYINT:
1281 /* SQL_TINYINT can be signed (e.g. MySQL) or */
1282 /* unsigned (e.g. MS SQL Server). We use a c_type */
1283 /* of SQL_C_SSHORT to be on the safe side. */
1284 case SQL_SMALLINT:
1285 c_type = SQL_C_SSHORT;
1286 buffer_length = sizeof(int16Type);
1287 break;
1288 case SQL_INTEGER:
1289 c_type = SQL_C_SLONG;
1290 buffer_length = sizeof(int32Type);
1291 break;
1292 case SQL_BIGINT:
1293 c_type = SQL_C_SBIGINT;
1294 buffer_length = sizeof(int64Type);
1295 break;
1296 case SQL_DECIMAL:
1297 c_type = SQL_C_CHAR;
1298 if (unlikely(columnDescr->columnSize > MAX_MEMSIZETYPE - 4)) {
1299 logError(printf("setupResultColumn: ColumnSize too big: " FMT_U_LEN "\n",
1300 columnDescr->columnSize););
1301 err_info = MEMORY_ERROR;
1302 } else {
1303 /* Add place for decimal point, sign, a possible */
1304 /* leading or trailing zero and a terminating null byte. */
1305 buffer_length = ((memSizeType) columnDescr->columnSize + 4);
1306 } /* if */
1307 /* printf("SQL_DECIMAL:\n");
1308 printf("columnSize: "FMT_U_MEM "\n", columnDescr->columnSize);
1309 printf("buffer_length: " FMT_U_MEM "\n", buffer_length);
1310 printf("decimalDigits: " FMT_D16 "\n", columnDescr->decimalDigits); */
1311 break;
1312 case SQL_NUMERIC:
1313 #if DECODE_NUMERIC_STRUCT
1314 c_type = SQL_C_NUMERIC;
1315 buffer_length = sizeof(SQL_NUMERIC_STRUCT);
1316 #else
1317 c_type = SQL_C_CHAR;
1318 if (columnDescr->columnSize < MIN_PRECISION_FOR_NUMERIC_AS_DECIMAL) {
1319 buffer_length = MIN_PRECISION_FOR_NUMERIC_AS_DECIMAL;
1320 } else if (columnDescr->columnSize > MAX_PRECISION_FOR_NUMERIC_AS_DECIMAL) {
1321 buffer_length = MAX_PRECISION_FOR_NUMERIC_AS_DECIMAL;
1322 } else {
1323 buffer_length = (memSizeType) columnDescr->columnSize;
1324 } /* if */
1325 /* Place for sign, decimal point and zero byte. */
1326 buffer_length += 3;
1327 #endif
1328 /* printf("SQL_NUMERIC:\n");
1329 printf("columnSize: " FMT_U_MEM "\n", columnDescr->columnSize);
1330 printf("buffer_length: " FMT_U_MEM "\n", buffer_length);
1331 printf("decimalDigits: " FMT_D16 "\n", columnDescr->decimalDigits); */
1332 break;
1333 case SQL_REAL:
1334 c_type = SQL_C_FLOAT;
1335 buffer_length = sizeof(float);
1336 break;
1337 case SQL_FLOAT:
1338 case SQL_DOUBLE:
1339 c_type = SQL_C_DOUBLE;
1340 buffer_length = sizeof(double);
1341 break;
1342 case SQL_TYPE_DATE:
1343 c_type = SQL_C_TYPE_DATE;
1344 buffer_length = sizeof(SQL_DATE_STRUCT);
1345 break;
1346 case SQL_TYPE_TIME:
1347 c_type = SQL_C_TYPE_TIME;
1348 buffer_length = sizeof(SQL_TIME_STRUCT);
1349 break;
1350 case SQL_DATETIME:
1351 case SQL_TYPE_TIMESTAMP:
1352 c_type = SQL_C_TYPE_TIMESTAMP;
1353 buffer_length = sizeof(SQL_TIMESTAMP_STRUCT);
1354 break;
1355 case SQL_INTERVAL_YEAR:
1356 c_type = SQL_C_INTERVAL_YEAR;
1357 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1358 break;
1359 case SQL_INTERVAL_MONTH:
1360 c_type = SQL_C_INTERVAL_MONTH;
1361 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1362 break;
1363 case SQL_INTERVAL_DAY:
1364 c_type = SQL_C_INTERVAL_DAY;
1365 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1366 break;
1367 case SQL_INTERVAL_HOUR:
1368 c_type = SQL_C_INTERVAL_HOUR;
1369 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1370 break;
1371 case SQL_INTERVAL_MINUTE:
1372 c_type = SQL_C_INTERVAL_MINUTE;
1373 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1374 break;
1375 case SQL_INTERVAL_SECOND:
1376 c_type = SQL_C_INTERVAL_SECOND;
1377 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1378 break;
1379 case SQL_INTERVAL_YEAR_TO_MONTH:
1380 c_type = SQL_C_INTERVAL_YEAR_TO_MONTH;
1381 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1382 break;
1383 case SQL_INTERVAL_DAY_TO_HOUR:
1384 c_type = SQL_C_INTERVAL_DAY_TO_HOUR;
1385 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1386 break;
1387 case SQL_INTERVAL_DAY_TO_MINUTE:
1388 c_type = SQL_C_INTERVAL_DAY_TO_MINUTE;
1389 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1390 break;
1391 case SQL_INTERVAL_DAY_TO_SECOND:
1392 c_type = SQL_C_INTERVAL_DAY_TO_SECOND;
1393 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1394 break;
1395 case SQL_INTERVAL_HOUR_TO_MINUTE:
1396 c_type = SQL_C_INTERVAL_HOUR_TO_MINUTE;
1397 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1398 break;
1399 case SQL_INTERVAL_HOUR_TO_SECOND:
1400 c_type = SQL_C_INTERVAL_HOUR_TO_SECOND;
1401 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1402 break;
1403 case SQL_INTERVAL_MINUTE_TO_SECOND:
1404 c_type = SQL_C_INTERVAL_MINUTE_TO_SECOND;
1405 buffer_length = sizeof(SQL_INTERVAL_STRUCT);
1406 break;
1407 case SQL_BLOB:
1408 columnDescr->dataType = SQL_LONGVARBINARY;
1409 c_type = SQL_C_BINARY;
1410 columnDescr->sql_data_at_exec = TRUE;
1411 buffer_length = (memSizeType) SQL_DATA_AT_EXEC;
1412 break;
1413 case SQL_CLOB:
1414 case SQL_XML:
1415 columnDescr->dataType = SQL_LONGVARCHAR;
1416 if (preparedStmt->db->wideCharsSupported) {
1417 c_type = SQL_C_WCHAR;
1418 } else {
1419 c_type = SQL_C_CHAR;
1420 } /* if */
1421 columnDescr->sql_data_at_exec = TRUE;
1422 buffer_length = (memSizeType) SQL_DATA_AT_EXEC;
1423 break;
1424 case SQL_SS_TIME2:
1425 c_type = SQL_C_BINARY;
1426 buffer_length = sizeof(sqlSsTime2Struct);
1427 break;
1428 default:
1429 logError(printf("setupResultColumn: Column %hd has the unknown type %s.\n",
1430 column_num, nameOfSqlType(columnDescr->dataType)););
1431 err_info = RANGE_ERROR;
1432 break;
1433 } /* switch */
1434 if (err_info == OKAY_NO_ERROR) {
1435 /* printf("c_type: %s\n", nameOfCType(c_type)); */
1436 /* printf("buffer_length[%d]: " FMT_U_MEM " %d\n",
1437 column_num, buffer_length, columnDescr->sql_data_at_exec); */
1438 columnDescr->c_type = c_type;
1439 columnDescr->buffer_length = buffer_length;
1440 } /* if */
1441 } /* if */
1442 logFunction(printf("setupResultColumn --> %d\n", err_info););
1443 return err_info;
1444 } /* setupResultColumn */
1445
1446
1447
setupResult(preparedStmtType preparedStmt)1448 static errInfoType setupResult (preparedStmtType preparedStmt)
1449
1450 {
1451 SQLRETURN returnCode;
1452 SQLSMALLINT num_columns;
1453 SQLSMALLINT column_index;
1454 boolType blobFound = FALSE;
1455 errInfoType err_info = OKAY_NO_ERROR;
1456
1457 /* setupResult */
1458 logFunction(printf("setupResult\n"););
1459 returnCode = SQLNumResultCols(preparedStmt->ppStmt, &num_columns);
1460 /* printf("returnCode: " FMT_D16 "\n", returnCode); */
1461 if (unlikely(returnCode != SQL_SUCCESS)) {
1462 setDbErrorMsg("setupResult", "SQLNumResultCols",
1463 SQL_HANDLE_STMT, preparedStmt->ppStmt);
1464 logError(printf("setupResult: SQLNumResultCols:\n%s\n",
1465 dbError.message););
1466 err_info = DATABASE_ERROR;
1467 } else if (unlikely(num_columns < 0)) {
1468 dbInconsistent("setupResult", "SQLNumResultCols");
1469 logError(printf("setupResult: SQLNumResultCols returns negative number: %hd\n",
1470 num_columns););
1471 err_info = DATABASE_ERROR;
1472 } else if (num_columns == 0) {
1473 /* malloc(0) may return NULL, which would wrongly trigger a MEMORY_ERROR. */
1474 preparedStmt->result_array_size = 0;
1475 preparedStmt->result_descr_array = NULL;
1476 } else if (unlikely(!ALLOC_TABLE(preparedStmt->result_descr_array,
1477 resultDescrRecord, (memSizeType) num_columns))) {
1478 err_info = MEMORY_ERROR;
1479 } else {
1480 preparedStmt->result_array_size = (memSizeType) num_columns;
1481 memset(preparedStmt->result_descr_array, 0,
1482 (memSizeType) num_columns * sizeof(resultDescrRecord));
1483 for (column_index = 0; column_index < num_columns &&
1484 err_info == OKAY_NO_ERROR; column_index++) {
1485 err_info = setupResultColumn(preparedStmt, (SQLSMALLINT) (column_index + 1),
1486 &preparedStmt->result_descr_array[column_index]);
1487 blobFound |= preparedStmt->result_descr_array[column_index].sql_data_at_exec;
1488 } /* for */
1489 preparedStmt->hasBlob = blobFound;
1490 } /* if */
1491 logFunction(printf("setupResult --> %d\n", err_info););
1492 return err_info;
1493 } /* setupResult */
1494
1495
1496
bindResultColumn(preparedStmtType preparedStmt,SQLSMALLINT column_num,resultDescrType columnDescr,resultDataType columnData,boolType blobFound)1497 static errInfoType bindResultColumn (preparedStmtType preparedStmt,
1498 SQLSMALLINT column_num, resultDescrType columnDescr,
1499 resultDataType columnData, boolType blobFound)
1500
1501 {
1502 errInfoType err_info = OKAY_NO_ERROR;
1503
1504 /* bindResultColumn */
1505 if (columnDescr->sql_data_at_exec) {
1506 columnData->buffer = NULL;
1507 } else {
1508 columnData->buffer = malloc(columnDescr->buffer_length);
1509 if (unlikely(columnData->buffer == NULL)) {
1510 err_info = MEMORY_ERROR;
1511 } else {
1512 memset(columnData->buffer, 0, columnDescr->buffer_length);
1513 } /* if */
1514 } /* if */
1515 if (err_info == OKAY_NO_ERROR) {
1516 /* The data of blobs (sql_data_at_exec = TRUE) is retrieved */
1517 /* with SQLGetData(). According to the SQL Server Native */
1518 /* Client ODBC driver documentation SQLGetData() cannot */
1519 /* retrieve data in random column order. Additionally all */
1520 /* unbound columns processed with SQLGetData() must have */
1521 /* higher column ordinals than the bound columns in the */
1522 /* result set. Therefore binding of columns stops as soon */
1523 /* as a blob column is found and the data is retrieved with */
1524 /* SQLGetData(). */
1525 if (!columnDescr->sql_data_at_exec && !blobFound) {
1526 /* printf("SQLBindCol(" FMT_U_MEM ", %d, " FMT_U_MEM ", ...)\n",
1527 preparedStmt->ppStmt,
1528 (int) column_num, columnDescr->buffer_length); */
1529 if (SQLBindCol(preparedStmt->ppStmt,
1530 (SQLUSMALLINT) column_num,
1531 columnDescr->c_type,
1532 columnData->buffer,
1533 (SQLLEN) columnDescr->buffer_length,
1534 &columnData->length) != SQL_SUCCESS) {
1535 setDbErrorMsg("bindResultColumn", "SQLBindCol",
1536 SQL_HANDLE_STMT, preparedStmt->ppStmt);
1537 logError(printf("bindResultColumn: SQLBindCol "
1538 "c_type: %d = %s:\n%s\n",
1539 columnDescr->c_type,
1540 nameOfCType(columnDescr->c_type),
1541 dbError.message););
1542 err_info = DATABASE_ERROR;
1543 #if DECODE_NUMERIC_STRUCT
1544 } else if (columnDescr->c_type == SQL_C_NUMERIC) {
1545 err_info = setNumericPrecisionAndScale(preparedStmt, column_num,
1546 columnDescr, columnData, TRUE);
1547 #endif
1548 } /* if */
1549 #if DECODE_NUMERIC_STRUCT
1550 } else if (columnDescr->c_type == SQL_C_NUMERIC) {
1551 err_info = setNumericPrecisionAndScale(preparedStmt, column_num,
1552 columnDescr, columnData, FALSE);
1553 #endif
1554 } /* if */
1555 } /* if */
1556 return err_info;
1557 } /* bindResultColumn */
1558
1559
1560
bindResult(preparedStmtType preparedStmt,fetchDataType fetchData)1561 static errInfoType bindResult (preparedStmtType preparedStmt, fetchDataType fetchData)
1562
1563 {
1564 memSizeType column_index;
1565 boolType blobFound = FALSE;
1566 errInfoType err_info = OKAY_NO_ERROR;
1567
1568 /* bindResult */
1569 logFunction(printf("bindResult\n"););
1570 if (preparedStmt->result_array_size == 0) {
1571 /* malloc(0) may return NULL, which would wrongly trigger a MEMORY_ERROR. */
1572 fetchData->result_array = NULL;
1573 } else if (unlikely(!ALLOC_TABLE(fetchData->result_array, resultDataRecord,
1574 preparedStmt->result_array_size))) {
1575 err_info = MEMORY_ERROR;
1576 } else {
1577 memset(fetchData->result_array, 0,
1578 preparedStmt->result_array_size * sizeof(resultDataRecord));
1579 for (column_index = 0; column_index < preparedStmt->result_array_size &&
1580 err_info == OKAY_NO_ERROR; column_index++) {
1581 err_info = bindResultColumn(preparedStmt, (SQLSMALLINT) (column_index + 1),
1582 &preparedStmt->result_descr_array[column_index],
1583 &fetchData->result_array[column_index],
1584 blobFound);
1585 blobFound |= preparedStmt->result_descr_array[column_index].sql_data_at_exec;
1586 } /* for */
1587 } /* if */
1588 logFunction(printf("bindResult --> %d\n", err_info););
1589 return err_info;
1590 } /* bindResult */
1591
1592
1593
copyNonBlobBuffers(resultDescrType columnDescr,resultDataType srcColumnData,resultDataType destColumnData)1594 static errInfoType copyNonBlobBuffers (resultDescrType columnDescr,
1595 resultDataType srcColumnData, resultDataType destColumnData)
1596
1597 {
1598 errInfoType err_info = OKAY_NO_ERROR;
1599
1600 /* copyNonBlobBuffers */
1601 if (!columnDescr->sql_data_at_exec) {
1602 /* Copy the buffer contents from source to destination. */
1603 destColumnData->buffer = malloc(columnDescr->buffer_length);
1604 if (unlikely(destColumnData->buffer == NULL)) {
1605 err_info = MEMORY_ERROR;
1606 } else {
1607 memcpy(destColumnData->buffer, srcColumnData->buffer, columnDescr->buffer_length);
1608 destColumnData->length = srcColumnData->length;
1609 } /* if */
1610 } /* if */
1611 return err_info;
1612 } /* copyNonBlobBuffers */
1613
1614
1615
moveBlobBuffers(resultDescrType columnDescr,resultDataType srcColumnData,resultDataType destColumnData)1616 static void moveBlobBuffers (resultDescrType columnDescr,
1617 resultDataType srcColumnData, resultDataType destColumnData)
1618
1619 { /* moveBlobBuffers */
1620 if (columnDescr->sql_data_at_exec) {
1621 /* Copy the buffer pointer from source to destination. */
1622 destColumnData->buffer = srcColumnData->buffer;
1623 destColumnData->length = srcColumnData->length;
1624 srcColumnData->buffer = NULL;
1625 srcColumnData->length = 0;
1626 } /* if */
1627 } /* moveBlobBuffers */
1628
1629
1630
copyFetchData(preparedStmtType preparedStmt,fetchDataType source)1631 static fetchDataType copyFetchData (preparedStmtType preparedStmt, fetchDataType source)
1632
1633 {
1634 memSizeType column_index;
1635 errInfoType err_info = OKAY_NO_ERROR;
1636 fetchDataType fetchData;
1637
1638 /* copyFetchData */
1639 logFunction(printf("copyFetchData\n"););
1640 if (likely(ALLOC_RECORD2(fetchData, fetchDataRecord,
1641 count.fetch_data, count.fetch_data_bytes))) {
1642 memset(fetchData, 0, sizeof(fetchDataRecord));
1643 if (preparedStmt->result_array_size == 0) {
1644 /* malloc(0) may return NULL, which would wrongly trigger a MEMORY_ERROR. */
1645 fetchData->result_array = NULL;
1646 } else if (unlikely(!ALLOC_TABLE(fetchData->result_array, resultDataRecord,
1647 preparedStmt->result_array_size))) {
1648 FREE_RECORD2(fetchData, fetchDataRecord,
1649 count.fetch_data, count.fetch_data_bytes);
1650 fetchData = NULL;
1651 } else {
1652 memset(fetchData->result_array, 0,
1653 preparedStmt->result_array_size * sizeof(resultDataRecord));
1654 for (column_index = 0; column_index < preparedStmt->result_array_size &&
1655 err_info == OKAY_NO_ERROR; column_index++) {
1656 err_info = copyNonBlobBuffers(&preparedStmt->result_descr_array[column_index],
1657 &source->result_array[column_index],
1658 &fetchData->result_array[column_index]);
1659 } /* for */
1660 if (unlikely(err_info != OKAY_NO_ERROR)) {
1661 freeFetch(preparedStmt, fetchData);
1662 fetchData = NULL;
1663 } else {
1664 for (column_index = 0; column_index < preparedStmt->result_array_size;
1665 column_index++) {
1666 moveBlobBuffers(&preparedStmt->result_descr_array[column_index],
1667 &source->result_array[column_index],
1668 &fetchData->result_array[column_index]);
1669 } /* for */
1670 } /* if */
1671 } /* if */
1672 } /* if */
1673 return fetchData;
1674 } /* copyFetchData */
1675
1676
1677
allParametersBound(preparedStmtType preparedStmt)1678 static boolType allParametersBound (preparedStmtType preparedStmt)
1679
1680 {
1681 memSizeType column_index;
1682 boolType okay = TRUE;
1683
1684 /* allParametersBound */
1685 for (column_index = 0; column_index < preparedStmt->param_array_size;
1686 column_index++) {
1687 if (unlikely(!preparedStmt->param_array[column_index].bound)) {
1688 logError(printf("sqlExecute: Unbound parameter " FMT_U_MEM ".\n",
1689 column_index + 1););
1690 okay = FALSE;
1691 } /* if */
1692 } /* for */
1693 return okay;
1694 } /* allParametersBound */
1695
1696
1697
1698 #if DECODE_NUMERIC_STRUCT
getNumericAsCStri(SQL_NUMERIC_STRUCT * numStruct)1699 static cstriType getNumericAsCStri (SQL_NUMERIC_STRUCT *numStruct)
1700
1701 {
1702 bigIntType mantissa;
1703 striType stri;
1704 memSizeType decimalLen;
1705 memSizeType decimalIdx = 0;
1706 memSizeType idx;
1707 cstriType decimal;
1708
1709 /* getNumericAsCStri */
1710 mantissa = bigFromByteBufferLe(SQL_MAX_NUMERIC_LEN, numStruct->val, FALSE);
1711 if (unlikely(mantissa == NULL)) {
1712 decimal = NULL;
1713 } else {
1714 stri = bigStr(mantissa);
1715 if (unlikely(stri == NULL)) {
1716 bigDestr(mantissa);
1717 raise_error(MEMORY_ERROR);
1718 decimal = NULL;
1719 } else {
1720 if (numStruct->scale < 0) {
1721 decimalLen = stri->size + (memSizeType) (-numStruct->scale) + 1 /* Space for decimal point */;
1722 } else if (numStruct->scale <= stri->size) {
1723 decimalLen = stri->size + 1 /* Space for decimal point */;
1724 } else {
1725 decimalLen = (memSizeType) numStruct->scale + 1 /* Space for decimal point */;
1726 } /* if */
1727 if (numStruct->sign != 1) {
1728 decimalLen++; /* Space for sign */
1729 } /* if */
1730 if (unlikely(!ALLOC_CSTRI(decimal, decimalLen))) {
1731 bigDestr(mantissa);
1732 strDestr(stri);
1733 raise_error(MEMORY_ERROR);
1734 } else {
1735 if (numStruct->sign != 1) {
1736 decimal[decimalIdx++] = '-';
1737 } /* if */
1738 for (idx = 0; idx < stri->size; idx++) {
1739 decimal[decimalIdx++] = (char) stri->mem[idx];
1740 } /* for */
1741 /* decimal[decimalIdx] = '\0';
1742 printf("# \"%s\", scale: %d, size: " FMT_U_MEM ", len: " FMT_U_MEM "\n",
1743 decimal, numStruct->scale, stri->size, decimalLen); */
1744 if (numStruct->scale < 0) {
1745 memset(&decimal[decimalIdx], '0', (memSizeType) (-numStruct->scale));
1746 decimal[decimalLen - 1] = '.';
1747 decimal[decimalLen] = '\0';
1748 } else if (numStruct->scale <= stri->size) {
1749 memmove(&decimal[decimalLen - (memSizeType) numStruct->scale],
1750 &decimal[decimalLen - (memSizeType) numStruct->scale - 1],
1751 (memSizeType) numStruct->scale);
1752 decimal[decimalLen - (memSizeType) numStruct->scale - 1] = '.';
1753 decimal[decimalLen] = '\0';
1754 } else {
1755 memmove(&decimal[decimalLen - stri->size],
1756 &decimal[decimalLen - (memSizeType) numStruct->scale - 1],
1757 stri->size);
1758 memset(&decimal[decimalLen - (memSizeType) numStruct->scale], '0',
1759 (memSizeType) numStruct->scale - stri->size);
1760 decimal[decimalLen - (memSizeType) numStruct->scale - 1] = '.';
1761 decimal[decimalLen] = '\0';
1762 } /* if */
1763 bigDestr(mantissa);
1764 strDestr(stri);
1765 } /* if */
1766 } /* if */
1767 } /* if */
1768 logFunction(printf("getNumericAsCStri --> %s\n", decimal));
1769 return decimal;
1770 } /* getNumericAsCStri */
1771
1772
1773
getNumericInt(const void * buffer)1774 static intType getNumericInt (const void *buffer)
1775
1776 {
1777 SQL_NUMERIC_STRUCT *numStruct;
1778 bigIntType bigIntValue;
1779 bigIntType powerOfTen;
1780 intType intValue = 0;
1781
1782 /* getNumericInt */
1783 numStruct = (SQL_NUMERIC_STRUCT *) buffer;
1784 logFunction(printf("getNumericInt\n");
1785 printf("numStruct->precision: %u\n", numStruct->precision);
1786 printf("numStruct->scale: %d\n", numStruct->scale);
1787 printf("numStruct->sign: %u\n", numStruct->sign);
1788 printf("numStruct->val:");
1789 {
1790 int pos;
1791 for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
1792 printf(" %d", numStruct->val[pos]);
1793 }
1794 printf("\n");
1795 });
1796 if (unlikely(numStruct->scale > 0)) {
1797 raise_error(RANGE_ERROR);
1798 intValue = 0;
1799 } else {
1800 bigIntValue = bigFromByteBufferLe(SQL_MAX_NUMERIC_LEN, numStruct->val, FALSE);
1801 #if 0
1802 if (bigIntValue != NULL) {
1803 printf("numStruct->val: ");
1804 prot_bigint(bigIntValue);
1805 printf("\n");
1806 }
1807 #endif
1808 if (bigIntValue != NULL && numStruct->scale < 0) {
1809 powerOfTen = bigIPowSignedDigit(10, (intType) -numStruct->scale);
1810 if (powerOfTen != NULL) {
1811 bigMultAssign(&bigIntValue, powerOfTen);
1812 bigDestr(powerOfTen);
1813 } /* if */
1814 } /* if */
1815 if (bigIntValue != NULL && numStruct->sign != 1) {
1816 bigIntValue = bigNegateTemp(bigIntValue);
1817 } /* if */
1818 if (bigIntValue != NULL) {
1819 #if 0
1820 printf("numStruct->val: ");
1821 prot_bigint(bigIntValue);
1822 printf("\n");
1823 #endif
1824 #if INTTYPE_SIZE == 32
1825 intValue = bigToInt32(bigIntValue, NULL);
1826 #elif INTTYPE_SIZE == 64
1827 intValue = bigToInt64(bigIntValue, NULL);
1828 #endif
1829 bigDestr(bigIntValue);
1830 } /* if */
1831 } /* if */
1832 logFunction(printf("getNumericInt --> " FMT_D "\n", intValue););
1833 return intValue;
1834 } /* getNumericInt */
1835
1836
1837
getNumericBigInt(const void * buffer)1838 static bigIntType getNumericBigInt (const void *buffer)
1839
1840 {
1841 SQL_NUMERIC_STRUCT *numStruct;
1842 bigIntType powerOfTen;
1843 bigIntType bigIntValue;
1844
1845 /* getNumericBigInt */
1846 numStruct = (SQL_NUMERIC_STRUCT *) buffer;
1847 logFunction(printf("getNumericBigInt\n");
1848 printf("numStruct->precision: %u\n", numStruct->precision);
1849 printf("numStruct->scale: %d\n", numStruct->scale);
1850 printf("numStruct->sign: %u\n", numStruct->sign);
1851 printf("numStruct->val:");
1852 {
1853 int pos;
1854 for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
1855 printf(" %d", numStruct->val[pos]);
1856 }
1857 printf("\n");
1858 });
1859 if (unlikely(numStruct->scale > 0)) {
1860 raise_error(RANGE_ERROR);
1861 bigIntValue = NULL;
1862 } else {
1863 bigIntValue = bigFromByteBufferLe(SQL_MAX_NUMERIC_LEN, numStruct->val, FALSE);
1864 #if 0
1865 if (bigIntValue != NULL) {
1866 printf("numStruct->val: ");
1867 prot_bigint(bigIntValue);
1868 printf("\n");
1869 } /* if */
1870 #endif
1871 if (bigIntValue != NULL && numStruct->scale < 0) {
1872 powerOfTen = bigIPowSignedDigit(10, (intType) -numStruct->scale);
1873 if (powerOfTen != NULL) {
1874 bigMultAssign(&bigIntValue, powerOfTen);
1875 bigDestr(powerOfTen);
1876 } /* if */
1877 } /* if */
1878 if (bigIntValue != NULL && numStruct->sign != 1) {
1879 bigIntValue = bigNegateTemp(bigIntValue);
1880 } /* if */
1881 } /* if */
1882 logFunction(printf("getNumericBigInt --> ");
1883 prot_bigint(bigIntValue);
1884 printf("\n"););
1885 return bigIntValue;
1886 } /* getNumericBigInt */
1887
1888
1889
getNumericBigRational(const void * buffer,bigIntType * denominator)1890 static bigIntType getNumericBigRational (const void *buffer, bigIntType *denominator)
1891
1892 {
1893 SQL_NUMERIC_STRUCT *numStruct;
1894 bigIntType powerOfTen;
1895 bigIntType numerator;
1896
1897 /* getNumericBigRational */
1898 numStruct = (SQL_NUMERIC_STRUCT *) buffer;
1899 logFunction(printf("getNumericBigRational\n");
1900 printf("numStruct->precision: %u\n", numStruct->precision);
1901 printf("numStruct->scale: %d\n", numStruct->scale);
1902 printf("numStruct->sign: %u\n", numStruct->sign);
1903 printf("numStruct->val:");
1904 {
1905 int pos;
1906 for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
1907 printf(" %d", numStruct->val[pos]);
1908 }
1909 printf("\n");
1910 });
1911 numerator = bigFromByteBufferLe(SQL_MAX_NUMERIC_LEN, numStruct->val, FALSE);
1912 #if 0
1913 if (numerator != NULL) {
1914 printf("numStruct->val: ");
1915 prot_bigint(numerator);
1916 printf("\n");
1917 } /* if */
1918 #endif
1919 if (numerator != NULL && numStruct->sign != 1) {
1920 numerator = bigNegateTemp(numerator);
1921 } /* if */
1922 if (numerator != NULL) {
1923 if (numStruct->scale < 0) {
1924 powerOfTen = bigIPowSignedDigit(10, (intType) -numStruct->scale);
1925 if (powerOfTen != NULL) {
1926 bigMultAssign(&numerator, powerOfTen);
1927 bigDestr(powerOfTen);
1928 } /* if */
1929 *denominator = bigFromInt32(1);
1930 } else {
1931 *denominator = bigIPowSignedDigit(10, (intType) numStruct->scale);
1932 } /* if */
1933 } /* if */
1934 return numerator;
1935 } /* getNumericBigRational */
1936
1937
1938
getNumericFloat(const void * buffer)1939 static floatType getNumericFloat (const void *buffer)
1940
1941 {
1942 SQL_NUMERIC_STRUCT *numStruct;
1943 cstriType decimal;
1944 floatType floatValue;
1945
1946 /* getNumericFloat */
1947 numStruct = (SQL_NUMERIC_STRUCT *) buffer;
1948 logFunction(printf("getNumericFloat\n");
1949 printf("numStruct->precision: %u\n", numStruct->precision);
1950 printf("numStruct->scale: %d\n", numStruct->scale);
1951 printf("numStruct->sign: %u\n", numStruct->sign);
1952 printf("numStruct->val:");
1953 {
1954 int pos;
1955 for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
1956 printf(" %d", numStruct->val[pos]);
1957 }
1958 printf("\n");
1959 });
1960 if (unlikely((decimal = getNumericAsCStri(numStruct)) == NULL)) {
1961 floatValue = 0.0;
1962 } else {
1963 floatValue = (floatType) strtod(decimal, NULL);
1964 UNALLOC_CSTRI(decimal, strlen(decimal));
1965 } /* if */
1966 logFunction(printf("getNumericFloat --> " FMT_E "\n", floatValue););
1967 return floatValue;
1968 } /* getNumericFloat */
1969 #endif
1970
1971
1972
getInt(const void * buffer,memSizeType length)1973 static intType getInt (const void *buffer, memSizeType length)
1974
1975 { /* getInt */
1976 #if DECODE_NUMERIC_STRUCT
1977 return getNumericInt(buffer);
1978 #else
1979 return getDecimalInt((const_ustriType) buffer, length);
1980 #endif
1981 } /* getInt */
1982
1983
1984
getBigInt(const void * buffer,memSizeType length)1985 static bigIntType getBigInt (const void *buffer, memSizeType length)
1986
1987 { /* getBigInt */
1988 #if DECODE_NUMERIC_STRUCT
1989 return getNumericBigInt(buffer);
1990 #else
1991 return getDecimalBigInt((const_ustriType) buffer, length);
1992 #endif
1993 } /* getBigInt */
1994
1995
1996
getBigRational(const void * buffer,memSizeType length,bigIntType * denominator)1997 static bigIntType getBigRational (const void *buffer, memSizeType length,
1998 bigIntType *denominator)
1999
2000 { /* getBigRational */
2001 #if DECODE_NUMERIC_STRUCT
2002 return getNumericBigRational(buffer, denominator);
2003 #else
2004 return getDecimalBigRational((const_ustriType) buffer, length, denominator);
2005 #endif
2006 } /* getBigRational */
2007
2008
2009
getFloat(const void * buffer,memSizeType length)2010 static floatType getFloat (const void *buffer, memSizeType length)
2011
2012 { /* getFloat */
2013 #if DECODE_NUMERIC_STRUCT
2014 return getNumericFloat(buffer);
2015 #else
2016 return getDecimalFloat((const_ustriType) buffer, length);
2017 #endif
2018 } /* getFloat */
2019
2020
2021
2022 #if ENCODE_NUMERIC_STRUCT
setNumericBigInt(void ** buffer,memSizeType * buffer_capacity,const const_bigIntType bigIntValue,errInfoType * err_info)2023 static memSizeType setNumericBigInt (void **buffer, memSizeType *buffer_capacity,
2024 const const_bigIntType bigIntValue, errInfoType *err_info)
2025
2026 {
2027 bigIntType absoluteValue;
2028 boolType negative;
2029 bstriType bstri;
2030 SQL_NUMERIC_STRUCT *numStruct;
2031
2032 /* setNumericBigInt */
2033 logFunction(printf("setNumericBigInt(*, *, %s, *)\n",
2034 bigHexCStri(bigIntValue)););
2035 if (*buffer_capacity < sizeof(SQL_NUMERIC_STRUCT)) {
2036 free(*buffer);
2037 if (unlikely((*buffer = malloc(sizeof(SQL_NUMERIC_STRUCT))) == NULL)) {
2038 *buffer_capacity = 0;
2039 *err_info = MEMORY_ERROR;
2040 } else {
2041 *buffer_capacity = sizeof(SQL_NUMERIC_STRUCT);
2042 } /* if */
2043 } /* if */
2044 if (likely(*err_info == OKAY_NO_ERROR)) {
2045 negative = bigCmpSignedDigit(bigIntValue, 0) < 0;
2046 if (negative) {
2047 absoluteValue = bigAbs(bigIntValue);
2048 if (absoluteValue == NULL) {
2049 bstri = NULL;
2050 } else {
2051 bstri = bigToBStriLe(absoluteValue, FALSE);
2052 bigDestr(absoluteValue);
2053 } /* if */
2054 } else {
2055 bstri = bigToBStriLe(bigIntValue, FALSE);
2056 } /* if */
2057 if (bstri == NULL) {
2058 *err_info = MEMORY_ERROR;
2059 } else {
2060 if (bstri->size > SQL_MAX_NUMERIC_LEN) {
2061 logError(printf("setNumericBigInt: Data with length " FMT_U_MEM
2062 " does not fit into a numeric.\n", bstri->size););
2063 *err_info = RANGE_ERROR;
2064 } else {
2065 numStruct = (SQL_NUMERIC_STRUCT *) *buffer;
2066 numStruct->precision = MAX_NUMERIC_PRECISION;
2067 numStruct->scale = 0;
2068 numStruct->sign = negative ? 0 : 1;
2069 memcpy(numStruct->val, bstri->mem, bstri->size);
2070 memset(&numStruct->val[bstri->size], 0, SQL_MAX_NUMERIC_LEN - bstri->size);
2071 } /* if */
2072 bstDestr(bstri);
2073 } /* if */
2074 } /* if */
2075 return sizeof(SQL_NUMERIC_STRUCT);
2076 } /* setNumericBigInt */
2077
2078
2079
setNumericBigRat(void ** buffer,const const_bigIntType numerator,const const_bigIntType denominator,SQLSMALLINT decimalDigits,errInfoType * err_info)2080 static memSizeType setNumericBigRat (void **buffer,
2081 const const_bigIntType numerator, const const_bigIntType denominator,
2082 SQLSMALLINT decimalDigits, errInfoType *err_info)
2083
2084 {
2085 bigIntType number;
2086 bigIntType mantissaValue = NULL;
2087 bigIntType absoluteValue;
2088 boolType negative;
2089 bstriType bstri;
2090 SQL_NUMERIC_STRUCT *numStruct;
2091
2092 /* setNumericBigRat */
2093 logFunction(printf("setNumericBigRat(*, %s, %s, " FMT_D16 ", *)\n",
2094 bigHexCStri(numerator), bigHexCStri(denominator),
2095 decimalDigits););
2096 if (*buffer != NULL) {
2097 free(*buffer);
2098 } /* if */
2099 *buffer = malloc(sizeof(SQL_NUMERIC_STRUCT));
2100 if (unlikely(*buffer == NULL)) {
2101 *err_info = MEMORY_ERROR;
2102 } else {
2103 if (unlikely(bigEqSignedDigit(denominator, 0))) {
2104 /* Numeric values do not support Infinity and NaN. */
2105 logError(printf("setNumericBigRat: Decimal values do not support Infinity and NaN.\n"););
2106 *err_info = RANGE_ERROR;
2107 } else {
2108 number = bigIPowSignedDigit(10, decimalDigits);
2109 if (number != NULL) {
2110 bigMultAssign(&number, numerator);
2111 mantissaValue = bigDiv(number, denominator);
2112 bigDestr(number);
2113 } /* if */
2114 if (mantissaValue != NULL) {
2115 /* printf("mantissaValue: ");
2116 prot_bigint(mantissaValue);
2117 printf("\n"); */
2118 negative = bigCmpSignedDigit(mantissaValue, 0) < 0;
2119 if (negative) {
2120 absoluteValue = bigAbs(mantissaValue);
2121 if (absoluteValue == NULL) {
2122 bstri = NULL;
2123 } else {
2124 bstri = bigToBStriLe(absoluteValue, FALSE);
2125 bigDestr(absoluteValue);
2126 } /* if */
2127 } else {
2128 bstri = bigToBStriLe(mantissaValue, FALSE);
2129 } /* if */
2130 if (bstri == NULL) {
2131 *err_info = MEMORY_ERROR;
2132 } else {
2133 if (bstri->size > SQL_MAX_NUMERIC_LEN) {
2134 logError(printf("setNumericBigRat: Data with length " FMT_U_MEM
2135 " does not fit into a numeric.\n", bstri->size););
2136 *err_info = RANGE_ERROR;
2137 } else {
2138 numStruct = (SQL_NUMERIC_STRUCT *) *buffer;
2139 numStruct->precision = MAX_NUMERIC_PRECISION;
2140 numStruct->scale = decimalDigits;
2141 numStruct->sign = negative ? 0 : 1;
2142 memcpy(numStruct->val, bstri->mem, bstri->size);
2143 memset(&numStruct->val[bstri->size], 0, SQL_MAX_NUMERIC_LEN - bstri->size);
2144 /* printf("setNumericToBigRat: \"%s\"\n", getNumericAsCStri(numStruct)); */
2145 #if 0
2146 printf("numStruct->precision: %u\n", numStruct->precision);
2147 printf("numStruct->scale: %d\n", numStruct->scale);
2148 printf("numStruct->sign: %u\n", numStruct->sign);
2149 printf("numStruct->val: ");
2150 prot_bigint(mantissaValue);
2151 printf("\n");
2152 { int pos; for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
2153 printf(" %d", numStruct->val[pos]); } printf("\n"); }
2154 #endif
2155 /*{
2156 bigIntType numerator2;
2157 bigIntType denominator2;
2158
2159 numerator2 = getNumericBigRational(*buffer, &denominator2);
2160 printf("stored: ");
2161 prot_bigint(numerator2);
2162 printf(" / ");
2163 prot_bigint(denominator2);
2164 printf("\n");
2165 } */
2166 } /* if */
2167 bstDestr(bstri);
2168 } /* if */
2169 bigDestr(mantissaValue);
2170 } /* if */
2171 } /* if */
2172 } /* if */
2173 return sizeof(SQL_NUMERIC_STRUCT);
2174 } /* setNumericBigRat */
2175 #endif
2176
2177
2178
setDecimalBigInt(void ** buffer,memSizeType * buffer_capacity,const const_bigIntType bigIntValue,errInfoType * err_info)2179 static memSizeType setDecimalBigInt (void **buffer, memSizeType *buffer_capacity,
2180 const const_bigIntType bigIntValue, errInfoType *err_info)
2181
2182 {
2183 striType stri;
2184 unsigned char *decimal;
2185 memSizeType srcIndex;
2186 memSizeType destIndex = 0;
2187
2188 /* setDecimalBigInt */
2189 logFunction(printf("setDecimalBigInt(*, *, %s, *)\n",
2190 bigHexCStri(bigIntValue)););
2191 stri = bigStr(bigIntValue);
2192 if (unlikely(stri == NULL)) {
2193 *err_info = MEMORY_ERROR;
2194 } else {
2195 /* printf("%s\n", striAsUnquotedCStri(stri)); */
2196 if (*buffer_capacity < stri->size + NULL_TERMINATION_LEN) {
2197 free(*buffer);
2198 *buffer = malloc(stri->size + NULL_TERMINATION_LEN);
2199 if (unlikely(*buffer == NULL)) {
2200 *buffer_capacity = 0;
2201 *err_info = MEMORY_ERROR;
2202 } else {
2203 *buffer_capacity = stri->size + NULL_TERMINATION_LEN;
2204 } /* if */
2205 } /* if */
2206 if (likely(*err_info == OKAY_NO_ERROR)) {
2207 decimal = (unsigned char *) *buffer;
2208 for (srcIndex = 0; srcIndex < stri->size; srcIndex++) {
2209 decimal[destIndex] = (unsigned char) stri->mem[srcIndex];
2210 destIndex++;
2211 } /* for */
2212 decimal[destIndex] = '\0';
2213 /* printf("%s\n", decimal); */
2214 } /* if */
2215 FREE_STRI(stri, stri->size);
2216 } /* if */
2217 return destIndex;
2218 } /* setDecimalBigInt */
2219
2220
2221
setDecimalBigRat(void ** buffer,const const_bigIntType numerator,const const_bigIntType denominator,SQLSMALLINT decimalDigits,errInfoType * err_info)2222 static memSizeType setDecimalBigRat (void **buffer,
2223 const const_bigIntType numerator, const const_bigIntType denominator,
2224 SQLSMALLINT decimalDigits, errInfoType *err_info)
2225
2226 {
2227 memSizeType length;
2228
2229 /* setDecimalBigRat */
2230 if (*buffer != NULL) {
2231 free(*buffer);
2232 } /* if */
2233 if (bigEqSignedDigit(denominator, 1)) {
2234 *buffer = bigIntToDecimal(numerator, &length, err_info);
2235 } else {
2236 *buffer = bigRatToDecimal(numerator, denominator, DEFAULT_DECIMAL_SCALE,
2237 &length, err_info);
2238 } /* if */
2239 return length;
2240 } /* setDecimalBigRat */
2241
2242
2243
setBigInt(void ** buffer,memSizeType * buffer_capacity,const const_bigIntType bigIntValue,errInfoType * err_info)2244 static memSizeType setBigInt (void **buffer, memSizeType *buffer_capacity,
2245 const const_bigIntType bigIntValue, errInfoType *err_info)
2246
2247 { /* setBigInt */
2248 #if ENCODE_NUMERIC_STRUCT
2249 return setNumericBigInt(buffer, buffer_capacity, bigIntValue, err_info);
2250 #else
2251 return setDecimalBigInt(buffer, buffer_capacity, bigIntValue, err_info);
2252 #endif
2253 } /* setBigInt */
2254
2255
2256
setBigRat(void ** buffer,memSizeType * buffer_capacity,const const_bigIntType numerator,const const_bigIntType denominator,SQLSMALLINT decimalDigits,errInfoType * err_info)2257 static memSizeType setBigRat (void **buffer, memSizeType *buffer_capacity,
2258 const const_bigIntType numerator, const const_bigIntType denominator,
2259 SQLSMALLINT decimalDigits, errInfoType *err_info)
2260
2261 {
2262 memSizeType length;
2263
2264 /* setBigRat */
2265 #if ENCODE_NUMERIC_STRUCT
2266 length = setNumericBigRat(buffer, numerator, denominator, decimalDigits,
2267 err_info);
2268 *buffer_capacity = length;
2269 #else
2270 length = setDecimalBigRat(buffer, numerator, denominator, decimalDigits,
2271 err_info);
2272 *buffer_capacity = length + NULL_TERMINATION_LEN;
2273 #endif
2274 return length;
2275 } /* setBigRat */
2276
2277
2278
assignToIntervalStruct(SQL_INTERVAL_STRUCT * interval,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second)2279 static SQLSMALLINT assignToIntervalStruct (SQL_INTERVAL_STRUCT *interval,
2280 intType year, intType month, intType day, intType hour,
2281 intType minute, intType second, intType micro_second)
2282
2283 {
2284 SQLSMALLINT c_type = 0;
2285
2286 /* assignToIntervalStruct */
2287 memset(interval, 0, sizeof(SQL_INTERVAL_STRUCT));
2288 if (day == 0 && hour == 0 && minute == 0 && second == 0 && micro_second == 0) {
2289 if (year != 0) {
2290 if (month != 0) {
2291 c_type = SQL_C_INTERVAL_YEAR_TO_MONTH;
2292 interval->interval_type = SQL_IS_YEAR_TO_MONTH;
2293 interval->interval_sign = year < 0 ? SQL_TRUE : SQL_FALSE;
2294 interval->intval.year_month.year = (SQLUINTEGER) abs((int) year);
2295 interval->intval.year_month.month = (SQLUINTEGER) abs((int) month);
2296 } else {
2297 c_type = SQL_C_INTERVAL_YEAR;
2298 interval->interval_type = SQL_IS_YEAR;
2299 interval->interval_sign = year < 0 ? SQL_TRUE : SQL_FALSE;
2300 interval->intval.year_month.year = (SQLUINTEGER) abs((int) year);
2301 } /* if */
2302 } else if (month != 0) {
2303 c_type = SQL_C_INTERVAL_MONTH;
2304 interval->interval_type = SQL_IS_MONTH;
2305 interval->interval_sign = month < 0 ? SQL_TRUE : SQL_FALSE;
2306 interval->intval.year_month.month = (SQLUINTEGER) abs((int) month);
2307 } else {
2308 c_type = SQL_C_INTERVAL_SECOND;
2309 interval->interval_type = SQL_IS_SECOND;
2310 interval->interval_sign = SQL_FALSE;
2311 interval->intval.day_second.second = 0;
2312 } /* if */
2313 } else if (year == 0 && month == 0) {
2314 if (day != 0) {
2315 if (second != 0) {
2316 c_type = SQL_C_INTERVAL_DAY_TO_SECOND;
2317 interval->interval_type = SQL_IS_DAY_TO_SECOND;
2318 interval->interval_sign = day < 0 ? SQL_TRUE : SQL_FALSE;
2319 interval->intval.day_second.day = (SQLUINTEGER) abs((int) day);
2320 interval->intval.day_second.hour = (SQLUINTEGER) abs((int) hour);
2321 interval->intval.day_second.minute = (SQLUINTEGER) abs((int) minute);
2322 interval->intval.day_second.second = (SQLUINTEGER) abs((int) second);
2323 } else if (minute != 0) {
2324 c_type = SQL_C_INTERVAL_DAY_TO_MINUTE;
2325 interval->interval_type = SQL_IS_DAY_TO_MINUTE;
2326 interval->interval_sign = day < 0 ? SQL_TRUE : SQL_FALSE;
2327 interval->intval.day_second.day = (SQLUINTEGER) abs((int) day);
2328 interval->intval.day_second.hour = (SQLUINTEGER) abs((int) hour);
2329 interval->intval.day_second.minute = (SQLUINTEGER) abs((int) minute);
2330 } else if (hour != 0) {
2331 c_type = SQL_C_INTERVAL_DAY_TO_HOUR;
2332 interval->interval_type = SQL_IS_DAY_TO_HOUR;
2333 interval->interval_sign = day < 0 ? SQL_TRUE : SQL_FALSE;
2334 interval->intval.day_second.day = (SQLUINTEGER) abs((int) day);
2335 interval->intval.day_second.hour = (SQLUINTEGER) abs((int) hour);
2336 } else {
2337 c_type = SQL_C_INTERVAL_DAY;
2338 interval->interval_type = SQL_IS_DAY;
2339 interval->interval_sign = day < 0 ? SQL_TRUE : SQL_FALSE;
2340 interval->intval.day_second.day = (SQLUINTEGER) abs((int) day);
2341 } /* if */
2342 } else if (hour != 0) {
2343 if (second != 0) {
2344 c_type = SQL_C_INTERVAL_HOUR_TO_SECOND;
2345 interval->interval_type = SQL_IS_HOUR_TO_SECOND;
2346 interval->interval_sign = hour < 0 ? SQL_TRUE : SQL_FALSE;
2347 interval->intval.day_second.hour = (SQLUINTEGER) abs((int) hour);
2348 interval->intval.day_second.minute = (SQLUINTEGER) abs((int) minute);
2349 interval->intval.day_second.second = (SQLUINTEGER) abs((int) second);
2350 } else if (minute != 0) {
2351 c_type = SQL_C_INTERVAL_HOUR_TO_MINUTE;
2352 interval->interval_type = SQL_IS_HOUR_TO_MINUTE;
2353 interval->interval_sign = hour < 0 ? SQL_TRUE : SQL_FALSE;
2354 interval->intval.day_second.hour = (SQLUINTEGER) abs((int) hour);
2355 interval->intval.day_second.minute = (SQLUINTEGER) abs((int) minute);
2356 } else {
2357 c_type = SQL_C_INTERVAL_HOUR;
2358 interval->interval_type = SQL_IS_HOUR;
2359 interval->interval_sign = hour < 0 ? SQL_TRUE : SQL_FALSE;
2360 interval->intval.day_second.hour = (SQLUINTEGER) abs((int) hour);
2361 } /* if */
2362 } else if (minute != 0) {
2363 if (second != 0) {
2364 c_type = SQL_C_INTERVAL_MINUTE_TO_SECOND;
2365 interval->interval_type = SQL_IS_MINUTE_TO_SECOND;
2366 interval->interval_sign = minute < 0 ? SQL_TRUE : SQL_FALSE;
2367 interval->intval.day_second.minute = (SQLUINTEGER) abs((int) minute);
2368 interval->intval.day_second.second = (SQLUINTEGER) abs((int) second);
2369 } else {
2370 c_type = SQL_C_INTERVAL_MINUTE;
2371 interval->interval_type = SQL_IS_MINUTE;
2372 interval->interval_sign = minute < 0 ? SQL_TRUE : SQL_FALSE;
2373 interval->intval.day_second.minute = (SQLUINTEGER) abs((int) minute);
2374 } /* if */
2375 } else {
2376 c_type = SQL_C_INTERVAL_SECOND;
2377 interval->interval_type = SQL_IS_SECOND;
2378 interval->interval_sign = second < 0 ? SQL_TRUE : SQL_FALSE;
2379 interval->intval.day_second.second = (SQLUINTEGER) abs((int) second);
2380 } /* if */
2381 interval->intval.day_second.fraction = (SQLUINTEGER) micro_second;
2382 } /* if */
2383 return c_type;
2384 } /* assignToIntervalStruct */
2385
2386
2387
getBlob(preparedStmtType preparedStmt,memSizeType column,resultDataType columnData,SQLSMALLINT targetType)2388 static errInfoType getBlob (preparedStmtType preparedStmt, memSizeType column,
2389 resultDataType columnData, SQLSMALLINT targetType)
2390
2391 {
2392 char ch;
2393 SQLLEN totalLength;
2394 SQLRETURN returnCode;
2395 cstriType buffer;
2396 errInfoType err_info = OKAY_NO_ERROR;
2397
2398 /* getBlob */
2399 logFunction(printf("getBlob(" FMT_U_MEM ", " FMT_U_MEM ")\n",
2400 (memSizeType) preparedStmt, column););
2401 if (columnData->buffer != NULL) {
2402 /* printf("getBlob: removing data\n"); */
2403 free(columnData->buffer);
2404 columnData->buffer = NULL;
2405 columnData->length = 0;
2406 } /* if */
2407 returnCode = SQLGetData(preparedStmt->ppStmt,
2408 (SQLUSMALLINT) column,
2409 targetType,
2410 &ch, 0, &totalLength);
2411 if (returnCode == SQL_SUCCESS || returnCode == SQL_SUCCESS_WITH_INFO) {
2412 if (totalLength == SQL_NO_TOTAL) {
2413 err_info = RANGE_ERROR;
2414 } else if (totalLength == SQL_NULL_DATA || totalLength == 0) {
2415 /* printf("Column is NULL or \"\" -> Use default value: \"\"\n"); */
2416 columnData->length = totalLength;
2417 } else if (unlikely(totalLength < 0)) {
2418 dbInconsistent("getBlob", "SQLGetData");
2419 logError(printf("getBlob: Column " FMT_U_MEM ": "
2420 "SQLGetData returns negative total length: " FMT_D_MEM "\n",
2421 column, totalLength););
2422 err_info = DATABASE_ERROR;
2423 } else {
2424 /* printf("totalLength=" FMT_D64 "\n", totalLength); */
2425 if (unlikely((SQLULEN) totalLength > MAX_CSTRI_LEN ||
2426 (buffer = (cstriType) malloc(
2427 SIZ_CSTRI((SQLULEN) totalLength))) == NULL)) {
2428 err_info = MEMORY_ERROR;
2429 } else {
2430 returnCode= SQLGetData(preparedStmt->ppStmt,
2431 (SQLUSMALLINT) column,
2432 targetType,
2433 buffer,
2434 SIZ_CSTRI(totalLength),
2435 &columnData->length);
2436 if (returnCode == SQL_SUCCESS || returnCode == SQL_SUCCESS_WITH_INFO) {
2437 columnData->buffer = buffer;
2438 } else {
2439 free(buffer);
2440 setDbErrorMsg("getBlob", "SQLGetData",
2441 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2442 logError(printf("getBlob: SQLGetData:\n%s\n",
2443 dbError.message););
2444 err_info = DATABASE_ERROR;
2445 } /* if */
2446 } /* if */
2447 } /* if */
2448 } else {
2449 /* printf("returnCode: " FMT_D16 "\n", returnCode); */
2450 setDbErrorMsg("getBlob", "SQLGetData",
2451 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2452 logError(printf("getBlob: SQLGetData:\n%s\n",
2453 dbError.message););
2454 err_info = DATABASE_ERROR;
2455 } /* if */
2456 logFunction(printf("getBlob --> %d\n", err_info););
2457 return err_info;
2458 } /* getBlob */
2459
2460
2461
getWClob(preparedStmtType preparedStmt,memSizeType column,resultDataType columnData)2462 static errInfoType getWClob (preparedStmtType preparedStmt, memSizeType column,
2463 resultDataType columnData)
2464
2465 {
2466 char ch;
2467 SQLLEN totalLength;
2468 memSizeType wstriLength;
2469 SQLRETURN returnCode;
2470 wstriType wstri;
2471 errInfoType err_info = OKAY_NO_ERROR;
2472
2473 /* getWClob */
2474 logFunction(printf("getWClob(" FMT_U_MEM ", " FMT_U_MEM ")\n",
2475 (memSizeType) preparedStmt, column););
2476 if (columnData->buffer != NULL) {
2477 /* printf("getWClob: removing data\n"); */
2478 free(columnData->buffer);
2479 columnData->buffer = NULL;
2480 columnData->length = 0;
2481 } /* if */
2482 returnCode = SQLGetData(preparedStmt->ppStmt,
2483 (SQLUSMALLINT) column,
2484 SQL_C_WCHAR,
2485 &ch, 0, &totalLength);
2486 if (returnCode == SQL_SUCCESS || returnCode == SQL_SUCCESS_WITH_INFO) {
2487 if (totalLength == SQL_NO_TOTAL) {
2488 err_info = RANGE_ERROR;
2489 } else if (totalLength == SQL_NULL_DATA || totalLength == 0) {
2490 /* printf("Column is NULL or \"\" -> Use default value: \"\"\n"); */
2491 columnData->length = totalLength;
2492 } else if (unlikely(totalLength < 0)) {
2493 dbInconsistent("getWClob", "SQLGetData");
2494 logError(printf("getWClob: Column " FMT_U_MEM ": "
2495 "SQLGetData returns negative total length: " FMT_D_LEN "\n",
2496 column, totalLength););
2497 err_info = DATABASE_ERROR;
2498 } else if (unlikely(totalLength > MAX_MEMSIZETYPE)){
2499 /* TotalLength is not representable as memSizeType. */
2500 /* Memory with this length cannot be allocated. */
2501 err_info = MEMORY_ERROR;
2502 } else {
2503 /* printf("totalLength=" FMT_D64 "\n", totalLength); */
2504 wstriLength = (memSizeType) totalLength / sizeof(wcharType);
2505 if (unlikely(wstriLength > MAX_WSTRI_LEN ||
2506 (wstri = (wstriType) malloc(SIZ_WSTRI(wstriLength))) == NULL)) {
2507 err_info = MEMORY_ERROR;
2508 } else {
2509 returnCode= SQLGetData(preparedStmt->ppStmt,
2510 (SQLUSMALLINT) column,
2511 SQL_C_WCHAR,
2512 wstri,
2513 (SQLLEN) SIZ_WSTRI(wstriLength),
2514 &columnData->length);
2515 if (returnCode == SQL_SUCCESS || returnCode == SQL_SUCCESS_WITH_INFO) {
2516 columnData->buffer = (cstriType) wstri;
2517 } else {
2518 free(wstri);
2519 setDbErrorMsg("getWClob", "SQLGetData",
2520 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2521 logError(printf("getWClob: SQLGetData:\n%s\n",
2522 dbError.message););
2523 err_info = DATABASE_ERROR;
2524 } /* if */
2525 } /* if */
2526 } /* if */
2527 } else {
2528 /* printf("returnCode: " FMT_D16 "\n", returnCode); */
2529 setDbErrorMsg("getWClob", "SQLGetData",
2530 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2531 logError(printf("getWClob: SQLGetData:\n%s\n",
2532 dbError.message););
2533 err_info = DATABASE_ERROR;
2534 } /* if */
2535 logFunction(printf("getWClob --> %d\n", err_info););
2536 return err_info;
2537 } /* getWClob */
2538
2539
2540
2541 /**
2542 * Get column data of an unbound column into an existing buffer.
2543 * The buffer is allocated by bindResultColumn(), but the column
2544 * is not bound with SQLBindCol(). This is done because this column
2545 * has a higher column ordinal than a blob column.
2546 */
getData(preparedStmtType preparedStmt,memSizeType column,resultDataType columnData)2547 static errInfoType getData (preparedStmtType preparedStmt, memSizeType column,
2548 resultDataType columnData)
2549
2550 {
2551 resultDescrType columnDescr;
2552 SQLSMALLINT c_type;
2553 SQLRETURN returnCode;
2554 errInfoType err_info = OKAY_NO_ERROR;
2555
2556 /* getData */
2557 logFunction(printf("getData(" FMT_U_MEM ", " FMT_U_MEM ")\n",
2558 (memSizeType) preparedStmt, column););
2559 columnDescr = &preparedStmt->result_descr_array[column - 1];
2560 c_type = columnDescr->c_type;
2561 #if DECODE_NUMERIC_STRUCT
2562 if (c_type == SQL_C_NUMERIC) {
2563 c_type = SQL_ARD_TYPE;
2564 } /* if */
2565 #endif
2566 returnCode= SQLGetData(preparedStmt->ppStmt,
2567 (SQLUSMALLINT) column,
2568 c_type,
2569 columnData->buffer,
2570 (SQLLEN) columnDescr->buffer_length,
2571 &columnData->length);
2572 if (returnCode != SQL_SUCCESS) {
2573 /* printf("returnCode: " FMT_D16 "\n", returnCode); */
2574 setDbErrorMsg("getData", "SQLGetData",
2575 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2576 logError(printf("getData: SQLGetData:\n%s\n",
2577 dbError.message););
2578 err_info = DATABASE_ERROR;
2579 } /* if */
2580 logFunction(printf("getData --> %d\n", err_info););
2581 return err_info;
2582 } /* getData */
2583
2584
2585
2586 /**
2587 * Get column data of blobs and all column data after the first blob.
2588 * The data of blobs (sql_data_at_exec = TRUE) is retrieved
2589 * with SQLGetData(). According to the SQL Server Native
2590 * Client ODBC driver documentation SQLGetData() cannot
2591 * retrieve data in random column order. Additionally all
2592 * unbound columns processed with SQLGetData must have
2593 * higher column ordinals than the bound columns in the
2594 * result set. Therefore binding of columns stops as soon
2595 * as a blob column is found and the data is retrieved with
2596 * SQLGetData().
2597 */
fetchBlobs(preparedStmtType preparedStmt,fetchDataType fetchData)2598 static errInfoType fetchBlobs (preparedStmtType preparedStmt, fetchDataType fetchData)
2599
2600 {
2601 memSizeType column;
2602 resultDescrType columnDescr;
2603 resultDataType columnData;
2604 boolType blobFound = FALSE;
2605 errInfoType err_info = OKAY_NO_ERROR;
2606
2607 /* fetchBlobs */
2608 logFunction(printf("fetchBlobs(" FMT_U_MEM ")\n",
2609 (memSizeType) preparedStmt););
2610 for (column = 1; column <= preparedStmt->result_array_size &&
2611 err_info == OKAY_NO_ERROR; column++) {
2612 columnDescr = &preparedStmt->result_descr_array[column - 1];
2613 columnData = &fetchData->result_array[column - 1];
2614 if (columnDescr->sql_data_at_exec) {
2615 blobFound = TRUE;
2616 /* printf("fetchBlobs: length: " FMT_D_LEN "\n", columnDescr->length); */
2617 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
2618 /* printf("c_type: %s\n", nameOfCType(columnDescr->c_type)); */
2619 switch (columnDescr->dataType) {
2620 case SQL_LONGVARCHAR:
2621 case SQL_WLONGVARCHAR:
2622 switch (columnDescr->c_type) {
2623 case SQL_C_CHAR:
2624 err_info = getBlob(preparedStmt, column, columnData, SQL_C_CHAR);
2625 break;
2626 case SQL_C_WCHAR:
2627 err_info = getWClob(preparedStmt, column, columnData);
2628 break;
2629 default:
2630 logError(printf("fetchBlobs: Parameter " FMT_U_MEM
2631 " has the unknown C type %s.\n",
2632 column, nameOfCType(columnDescr->c_type)););
2633 err_info = RANGE_ERROR;
2634 break;
2635 } /* switch */
2636 break;
2637 case SQL_LONGVARBINARY:
2638 err_info = getBlob(preparedStmt, column, columnData, SQL_C_BINARY);
2639 break;
2640 default:
2641 logError(printf("fetchBlobs: Parameter " FMT_U_MEM
2642 " has the unknown type %s.\n",
2643 column, nameOfSqlType(columnDescr->dataType)););
2644 err_info = RANGE_ERROR;
2645 break;
2646 } /* switch */
2647 } else if (blobFound) {
2648 err_info = getData(preparedStmt, column, columnData);
2649 } /* if */
2650 } /* for */
2651 logFunction(printf("fetchBlobs --> %d\n", err_info););
2652 return err_info;
2653 } /* fetchBlobs */
2654
2655
2656
prefetchOne(preparedStmtType preparedStmt,fetchDataType boundFetchData,errInfoType * err_info)2657 static fetchDataType prefetchOne (preparedStmtType preparedStmt,
2658 fetchDataType boundFetchData, errInfoType *err_info)
2659
2660 {
2661 fetchDataType fetchData;
2662
2663 /* prefetchOne */
2664 logFunction(printf("prefetchOne\n"););
2665 boundFetchData->fetch_result = SQLFetch(preparedStmt->ppStmt);
2666 if (boundFetchData->fetch_result == SQL_SUCCESS) {
2667 if (preparedStmt->hasBlob) {
2668 *err_info = fetchBlobs(preparedStmt, boundFetchData);
2669 } /* if */
2670 if (unlikely(*err_info != OKAY_NO_ERROR)) {
2671 fetchData = NULL;
2672 } else {
2673 fetchData = copyFetchData(preparedStmt, boundFetchData);
2674 if (unlikely(fetchData == NULL)) {
2675 *err_info = MEMORY_ERROR;
2676 } else {
2677 fetchData->fetch_result = boundFetchData->fetch_result;
2678 } /* if */
2679 } /* if */
2680 } else if (boundFetchData->fetch_result == SQL_NO_DATA) {
2681 if (unlikely(!ALLOC_RECORD2(fetchData, fetchDataRecord,
2682 count.fetch_data, count.fetch_data_bytes))) {
2683 *err_info = MEMORY_ERROR;
2684 } else {
2685 memset(fetchData, 0, sizeof(fetchDataRecord));
2686 fetchData->fetch_result = boundFetchData->fetch_result;
2687 } /* if */
2688 } else {
2689 setDbErrorMsg("prefetchOne", "SQLFetch",
2690 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2691 logError(printf("prefetchOne: SQLFetch fetch_result: %d:\n%s\n",
2692 boundFetchData->fetch_result, dbError.message););
2693 *err_info = DATABASE_ERROR;
2694 fetchData = NULL;
2695 } /* if */
2696 logFunction(printf("prefetchOne --> " FMT_U_MEM " (err_info=%d)\n",
2697 (memSizeType) fetchData, *err_info););
2698 return fetchData;
2699 } /* prefetchOne */
2700
2701
2702
prefetchAll(preparedStmtType preparedStmt,fetchDataType boundFetchData)2703 static errInfoType prefetchAll (preparedStmtType preparedStmt, fetchDataType boundFetchData)
2704
2705 {
2706 fetchDataType *listEnd;
2707 fetchDataType fetchData;
2708 errInfoType err_info = OKAY_NO_ERROR;
2709
2710 /* prefetchAll */
2711 logFunction(printf("prefetchAll\n"););
2712 listEnd = &preparedStmt->prefetched;
2713 while ((fetchData = prefetchOne(preparedStmt, boundFetchData, &err_info)) != NULL &&
2714 fetchData->fetch_result == SQL_SUCCESS) {
2715 *listEnd = fetchData;
2716 listEnd = &fetchData->next;
2717 } /* while */
2718 if (fetchData != NULL && fetchData->fetch_result == SQL_NO_DATA) {
2719 *listEnd = fetchData;
2720 listEnd = &fetchData->next;
2721 } /* if */
2722 *listEnd = NULL;
2723 logFunction(printf("prefetchAll --> %d\n", err_info););
2724 return err_info;
2725 } /* prefetchAll */
2726
2727
2728
doFetch(preparedStmtType preparedStmt,fetchDataType boundFetchData)2729 static errInfoType doFetch (preparedStmtType preparedStmt, fetchDataType boundFetchData)
2730
2731 {
2732 errInfoType err_info = OKAY_NO_ERROR;
2733
2734 /* doFetch */
2735 if (preparedStmt->prefetched != NULL) {
2736 if (preparedStmt->currentFetch != NULL &&
2737 preparedStmt->currentFetch != boundFetchData) {
2738 freeFetch(preparedStmt, preparedStmt->currentFetch);
2739 } /* if */
2740 preparedStmt->currentFetch = preparedStmt->prefetched;
2741 preparedStmt->prefetched = preparedStmt->prefetched->next;
2742 preparedStmt->currentFetch->next = NULL;
2743 } else {
2744 boundFetchData->fetch_result = SQLFetch(preparedStmt->ppStmt);
2745 #ifdef ALLOW_FETCH_SUCCESS_WITH_INFO
2746 if (boundFetchData->fetch_result == SQL_SUCCESS_WITH_INFO) {
2747 boundFetchData->fetch_result = SQL_SUCCESS;
2748 } /*if */
2749 #endif
2750 if (boundFetchData->fetch_result == SQL_SUCCESS) {
2751 if (preparedStmt->hasBlob) {
2752 err_info = fetchBlobs(preparedStmt, boundFetchData);
2753 } /* if */
2754 if (unlikely(err_info != OKAY_NO_ERROR)) {
2755 preparedStmt->currentFetch = NULL;
2756 } else {
2757 boundFetchData->next = NULL;
2758 preparedStmt->currentFetch = boundFetchData;
2759 } /* if */
2760 } else if (boundFetchData->fetch_result == SQL_NO_DATA) {
2761 boundFetchData->next = NULL;
2762 preparedStmt->currentFetch = boundFetchData;
2763 } else {
2764 setDbErrorMsg("doFetch", "SQLFetch",
2765 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2766 logError(printf("doFetch: SQLFetch fetch_result: %d:\n%s\n",
2767 boundFetchData->fetch_result, dbError.message););
2768 err_info = DATABASE_ERROR;
2769 preparedStmt->currentFetch = NULL;
2770 } /* if */
2771 } /* if */
2772 return err_info;
2773 } /* doFetch */
2774
2775
2776
sqlBindBigInt(sqlStmtType sqlStatement,intType pos,const const_bigIntType value)2777 static void sqlBindBigInt (sqlStmtType sqlStatement, intType pos,
2778 const const_bigIntType value)
2779
2780 {
2781 preparedStmtType preparedStmt;
2782 bindDataType param;
2783 int16Type value16;
2784 SQLSMALLINT c_type;
2785 errInfoType err_info = OKAY_NO_ERROR;
2786
2787 /* sqlBindBigInt */
2788 logFunction(printf("sqlBindBigInt(" FMT_U_MEM ", " FMT_D ", %s)\n",
2789 (memSizeType) sqlStatement, pos, bigHexCStri(value)););
2790 preparedStmt = (preparedStmtType) sqlStatement;
2791 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
2792 logError(printf("sqlBindBigInt: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
2793 pos, preparedStmt->param_array_size););
2794 err_info = RANGE_ERROR;
2795 } else {
2796 if (preparedStmt->executeSuccessful) {
2797 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
2798 setDbErrorMsg("sqlBindBigInt", "SQLFreeStmt",
2799 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2800 logError(printf("sqlBindBigInt: SQLFreeStmt SQL_CLOSE:\n%s\n",
2801 dbError.message););
2802 err_info = DATABASE_ERROR;
2803 } else {
2804 preparedStmt->executeSuccessful = FALSE;
2805 freePrefetched(preparedStmt);
2806 } /* if */
2807 } /* if */
2808 if (likely(err_info == OKAY_NO_ERROR)) {
2809 param = &preparedStmt->param_array[pos - 1];
2810 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
2811 switch (param->dataType) {
2812 case SQL_BIT:
2813 value16 = bigToInt16(value, &err_info);
2814 if (likely(err_info == OKAY_NO_ERROR)) {
2815 if (unlikely(value16 < 0 || value16 > 1)) {
2816 logError(printf("sqlBindBigInt: Parameter " FMT_D ": "
2817 FMT_D16 " does not fit into a bit.\n",
2818 pos, value16));
2819 err_info = RANGE_ERROR;
2820 } else {
2821 c_type = SQL_C_BIT;
2822 *(char *) param->buffer = (char) value16;
2823 } /* if */
2824 } /* if */
2825 break;
2826 case SQL_TINYINT:
2827 value16 = bigToInt16(value, &err_info);
2828 if (likely(err_info == OKAY_NO_ERROR)) {
2829 if (preparedStmt->db->tinyintIsUnsigned) {
2830 if (unlikely(value16 < 0 || value16 > UINT8TYPE_MAX)) {
2831 logError(printf("sqlBindBigInt: Parameter " FMT_D ": "
2832 FMT_D16 " does not fit into a 8-bit unsigned integer.\n",
2833 pos, value16));
2834 err_info = RANGE_ERROR;
2835 } else {
2836 c_type = SQL_C_UTINYINT;
2837 *(uint8Type *) param->buffer = (uint8Type) value16;
2838 } /* if */
2839 } else {
2840 if (unlikely(value16 < INT8TYPE_MIN || value16 > INT8TYPE_MAX)) {
2841 logError(printf("sqlBindBigInt: Parameter " FMT_D ": "
2842 FMT_D16 " does not fit into a 8-bit signed integer.\n",
2843 pos, value16));
2844 err_info = RANGE_ERROR;
2845 } else {
2846 c_type = SQL_C_STINYINT;
2847 *(int8Type *) param->buffer = (int8Type) value16;
2848 } /* if */
2849 } /* if */
2850 } /* if */
2851 break;
2852 case SQL_SMALLINT:
2853 c_type = SQL_C_SSHORT;
2854 *(int16Type *) param->buffer = bigToInt16(value, &err_info);
2855 break;
2856 case SQL_INTEGER:
2857 c_type = SQL_C_SLONG;
2858 *(int32Type *) param->buffer = bigToInt32(value, &err_info);
2859 break;
2860 case SQL_BIGINT:
2861 c_type = SQL_C_SBIGINT;
2862 *(int64Type *) param->buffer = bigToInt64(value, &err_info);
2863 break;
2864 case SQL_REAL:
2865 c_type = SQL_C_FLOAT;
2866 *(float *) param->buffer = (float) bigIntToDouble(value);
2867 break;
2868 case SQL_FLOAT:
2869 case SQL_DOUBLE:
2870 c_type = SQL_C_DOUBLE;
2871 *(double *) param->buffer = bigIntToDouble(value);
2872 break;
2873 case SQL_DECIMAL:
2874 case SQL_NUMERIC:
2875 case SQL_CHAR:
2876 case SQL_VARCHAR:
2877 case SQL_LONGVARCHAR:
2878 #if ENCODE_NUMERIC_STRUCT
2879 c_type = SQL_C_NUMERIC,
2880 #else
2881 c_type = SQL_C_CHAR,
2882 #endif
2883 param->buffer_length = setBigInt(¶m->buffer,
2884 ¶m->buffer_capacity,
2885 value, &err_info);
2886 break;
2887 default:
2888 logError(printf("sqlBindBigInt: Parameter " FMT_D " has the unknown type %s.\n",
2889 pos, nameOfSqlType(param->dataType)););
2890 err_info = RANGE_ERROR;
2891 break;
2892 } /* switch */
2893 if (likely(err_info == OKAY_NO_ERROR)) {
2894 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
2895 (SQLUSMALLINT) pos,
2896 SQL_PARAM_INPUT,
2897 c_type,
2898 param->dataType,
2899 param->paramSize,
2900 param->decimalDigits,
2901 param->buffer,
2902 (SQLLEN) param->buffer_length,
2903 NULL) != SQL_SUCCESS)) {
2904 setDbErrorMsg("sqlBindBigInt", "SQLBindParameter",
2905 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2906 logError(printf("sqlBindBigInt: SQLBindParameter:\n%s\n",
2907 dbError.message););
2908 err_info = DATABASE_ERROR;
2909 } else {
2910 preparedStmt->fetchOkay = FALSE;
2911 param->bound = TRUE;
2912 } /* if */
2913 } /* if */
2914 } /* if */
2915 } /* if */
2916 if (unlikely(err_info != OKAY_NO_ERROR)) {
2917 raise_error(err_info);
2918 } /* if */
2919 } /* sqlBindBigInt */
2920
2921
2922
sqlBindBigRat(sqlStmtType sqlStatement,intType pos,const const_bigIntType numerator,const const_bigIntType denominator)2923 static void sqlBindBigRat (sqlStmtType sqlStatement, intType pos,
2924 const const_bigIntType numerator, const const_bigIntType denominator)
2925
2926 {
2927 preparedStmtType preparedStmt;
2928 bindDataType param;
2929 SQLSMALLINT c_type;
2930 errInfoType err_info = OKAY_NO_ERROR;
2931
2932 /* sqlBindBigRat */
2933 logFunction(printf("sqlBindBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s)\n",
2934 (memSizeType) sqlStatement, pos,
2935 bigHexCStri(numerator), bigHexCStri(denominator)););
2936 preparedStmt = (preparedStmtType) sqlStatement;
2937 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
2938 logError(printf("sqlBindBigRat: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
2939 pos, preparedStmt->param_array_size););
2940 err_info = RANGE_ERROR;
2941 } else {
2942 if (preparedStmt->executeSuccessful) {
2943 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
2944 setDbErrorMsg("sqlBindBigRat", "SQLFreeStmt",
2945 SQL_HANDLE_STMT, preparedStmt->ppStmt);
2946 logError(printf("sqlBindBigRat: SQLFreeStmt SQL_CLOSE:\n%s\n",
2947 dbError.message););
2948 err_info = DATABASE_ERROR;
2949 } else {
2950 preparedStmt->executeSuccessful = FALSE;
2951 freePrefetched(preparedStmt);
2952 } /* if */
2953 } /* if */
2954 if (likely(err_info == OKAY_NO_ERROR)) {
2955 param = &preparedStmt->param_array[pos - 1];
2956 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
2957 switch (param->dataType) {
2958 case SQL_DECIMAL:
2959 case SQL_NUMERIC:
2960 case SQL_VARCHAR:
2961 case SQL_LONGVARCHAR:
2962 #if ENCODE_NUMERIC_STRUCT
2963 c_type = SQL_C_NUMERIC,
2964 #else
2965 c_type = SQL_C_CHAR,
2966 #endif
2967 param->buffer_length =
2968 setBigRat(¶m->buffer, ¶m->buffer_capacity,
2969 numerator, denominator,
2970 param->decimalDigits, &err_info);
2971 break;
2972 case SQL_REAL:
2973 c_type = SQL_C_FLOAT;
2974 *(float *) param->buffer =
2975 (float) bigRatToDouble(numerator, denominator);
2976 break;
2977 case SQL_FLOAT:
2978 case SQL_DOUBLE:
2979 c_type = SQL_C_DOUBLE;
2980 *(double *) param->buffer =
2981 bigRatToDouble(numerator, denominator);
2982 break;
2983 default:
2984 logError(printf("sqlBindBigRat: Parameter " FMT_D " has the unknown type %s.\n",
2985 pos, nameOfSqlType(param->dataType)););
2986 err_info = RANGE_ERROR;
2987 break;
2988 } /* switch */
2989 if (likely(err_info == OKAY_NO_ERROR)) {
2990 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
2991 (SQLUSMALLINT) pos,
2992 SQL_PARAM_INPUT,
2993 c_type,
2994 param->dataType,
2995 param->paramSize,
2996 param->decimalDigits,
2997 param->buffer,
2998 (SQLLEN) param->buffer_length,
2999 NULL) != SQL_SUCCESS)) {
3000 setDbErrorMsg("sqlBindBigRat", "SQLBindParameter",
3001 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3002 logError(printf("sqlBindBigRat: SQLBindParameter:\n%s\n",
3003 dbError.message););
3004 err_info = DATABASE_ERROR;
3005 } else {
3006 preparedStmt->fetchOkay = FALSE;
3007 param->bound = TRUE;
3008 } /* if */
3009 } /* if */
3010 } /* if */
3011 } /* if */
3012 if (unlikely(err_info != OKAY_NO_ERROR)) {
3013 raise_error(err_info);
3014 } /* if */
3015 } /* sqlBindBigRat */
3016
3017
3018
sqlBindBool(sqlStmtType sqlStatement,intType pos,boolType value)3019 static void sqlBindBool (sqlStmtType sqlStatement, intType pos, boolType value)
3020
3021 {
3022 preparedStmtType preparedStmt;
3023 bindDataType param;
3024 SQLSMALLINT c_type;
3025 errInfoType err_info = OKAY_NO_ERROR;
3026
3027 /* sqlBindBool */
3028 logFunction(printf("sqlBindBool(" FMT_U_MEM ", " FMT_D ", %s)\n",
3029 (memSizeType) sqlStatement, pos, value ? "TRUE" : "FALSE"););
3030 preparedStmt = (preparedStmtType) sqlStatement;
3031 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3032 logError(printf("sqlBindBool: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3033 pos, preparedStmt->param_array_size););
3034 err_info = RANGE_ERROR;
3035 } else {
3036 if (preparedStmt->executeSuccessful) {
3037 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
3038 setDbErrorMsg("sqlBindBool", "SQLFreeStmt",
3039 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3040 logError(printf("sqlBindBool: SQLFreeStmt SQL_CLOSE:\n%s\n",
3041 dbError.message););
3042 err_info = DATABASE_ERROR;
3043 } else {
3044 preparedStmt->executeSuccessful = FALSE;
3045 freePrefetched(preparedStmt);
3046 } /* if */
3047 } /* if */
3048 if (likely(err_info == OKAY_NO_ERROR)) {
3049 param = &preparedStmt->param_array[pos - 1];
3050 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
3051 switch (param->dataType) {
3052 case SQL_BIT:
3053 c_type = SQL_C_BIT;
3054 *(char *) param->buffer = (char) value;
3055 break;
3056 case SQL_TINYINT:
3057 c_type = SQL_C_STINYINT;
3058 *(int8Type *) param->buffer = (int8Type) value;
3059 break;
3060 case SQL_SMALLINT:
3061 c_type = SQL_C_SSHORT;
3062 *(int16Type *) param->buffer = (int16Type) value;
3063 break;
3064 case SQL_INTEGER:
3065 c_type = SQL_C_SLONG;
3066 *(int32Type *) param->buffer = (int32Type) value;
3067 break;
3068 case SQL_BIGINT:
3069 c_type = SQL_C_SBIGINT;
3070 *(int64Type *) param->buffer = (int64Type) value;
3071 break;
3072 case SQL_REAL:
3073 c_type = SQL_C_FLOAT;
3074 *(float *) param->buffer = (float) value;
3075 break;
3076 case SQL_FLOAT:
3077 case SQL_DOUBLE:
3078 c_type = SQL_C_DOUBLE;
3079 *(double *) param->buffer = (double) value;
3080 break;
3081 case SQL_DECIMAL:
3082 case SQL_NUMERIC:
3083 case SQL_CHAR:
3084 case SQL_VARCHAR:
3085 case SQL_LONGVARCHAR:
3086 c_type = SQL_C_SLONG;
3087 if (param->buffer_capacity < sizeof(int32Type)) {
3088 free(param->buffer);
3089 if (unlikely((param->buffer = malloc(sizeof(int32Type))) == NULL)) {
3090 param->buffer_capacity = 0;
3091 err_info = MEMORY_ERROR;
3092 } else {
3093 param->buffer_capacity = sizeof(int32Type);
3094 } /* if */
3095 } /* if */
3096 if (likely(err_info == OKAY_NO_ERROR)) {
3097 param->buffer_length = sizeof(int32Type);
3098 *(int32Type *) param->buffer = (int32Type) value;
3099 } /* if */
3100 break;
3101 default:
3102 logError(printf("sqlBindBool: Parameter " FMT_D " has the unknown type %s.\n",
3103 pos, nameOfSqlType(param->dataType)););
3104 err_info = RANGE_ERROR;
3105 break;
3106 } /* switch */
3107 if (likely(err_info == OKAY_NO_ERROR)) {
3108 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
3109 (SQLUSMALLINT) pos,
3110 SQL_PARAM_INPUT,
3111 c_type,
3112 param->dataType,
3113 param->paramSize,
3114 param->decimalDigits,
3115 param->buffer,
3116 (SQLLEN) param->buffer_length,
3117 NULL) != SQL_SUCCESS)) {
3118 setDbErrorMsg("sqlBindBool", "SQLBindParameter",
3119 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3120 logError(printf("sqlBindBool: SQLBindParameter:\n%s\n",
3121 dbError.message););
3122 err_info = DATABASE_ERROR;
3123 } else {
3124 preparedStmt->fetchOkay = FALSE;
3125 param->bound = TRUE;
3126 } /* if */
3127 } /* if */
3128 } /* if */
3129 } /* if */
3130 if (unlikely(err_info != OKAY_NO_ERROR)) {
3131 raise_error(err_info);
3132 } /* if */
3133 } /* sqlBindBool */
3134
3135
3136
sqlBindBStri(sqlStmtType sqlStatement,intType pos,const const_bstriType bstri)3137 static void sqlBindBStri (sqlStmtType sqlStatement, intType pos,
3138 const const_bstriType bstri)
3139
3140 {
3141 preparedStmtType preparedStmt;
3142 bindDataType param;
3143 SQLSMALLINT c_type;
3144 memSizeType minimum_size;
3145 errInfoType err_info = OKAY_NO_ERROR;
3146
3147 /* sqlBindBStri */
3148 logFunction(printf("sqlBindBStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
3149 (memSizeType) sqlStatement, pos, bstriAsUnquotedCStri(bstri)););
3150 preparedStmt = (preparedStmtType) sqlStatement;
3151 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3152 logError(printf("sqlBindBStri: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3153 pos, preparedStmt->param_array_size););
3154 err_info = RANGE_ERROR;
3155 } else {
3156 if (preparedStmt->executeSuccessful) {
3157 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
3158 setDbErrorMsg("sqlBindBStri", "SQLFreeStmt",
3159 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3160 logError(printf("sqlBindBStri: SQLFreeStmt SQL_CLOSE:\n%s\n",
3161 dbError.message););
3162 err_info = DATABASE_ERROR;
3163 } else {
3164 preparedStmt->executeSuccessful = FALSE;
3165 freePrefetched(preparedStmt);
3166 } /* if */
3167 } /* if */
3168 if (likely(err_info == OKAY_NO_ERROR)) {
3169 param = &preparedStmt->param_array[pos - 1];
3170 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
3171 switch (param->dataType) {
3172 case SQL_BINARY:
3173 case SQL_VARBINARY:
3174 case SQL_LONGVARBINARY:
3175 case SQL_VARCHAR:
3176 case SQL_LONGVARCHAR:
3177 case SQL_BLOB:
3178 case SQL_CLOB:
3179 c_type = SQL_C_BINARY;
3180 if (unlikely(bstri->size > SQLLEN_MAX)) {
3181 /* It is not possible to cast bstri->size to SQLLEN. */
3182 err_info = MEMORY_ERROR;
3183 } else {
3184 /* Use a buffer size with at least one byte. */
3185 minimum_size = bstri->size == 0 ? 1 : bstri->size;
3186 if (param->buffer_capacity < minimum_size) {
3187 free(param->buffer);
3188 if (unlikely((param->buffer = malloc(minimum_size)) == NULL)) {
3189 param->buffer_capacity = 0;
3190 err_info = MEMORY_ERROR;
3191 } else {
3192 param->buffer_capacity = minimum_size;
3193 } /* if */
3194 } /* if */
3195 if (likely(err_info == OKAY_NO_ERROR)) {
3196 memcpy(param->buffer, bstri->mem, bstri->size);
3197 param->buffer_length = bstri->size;
3198 /* The length is necessary to avoid that a zero byte terminates the data. */
3199 param->length = (SQLLEN) bstri->size;
3200 } /* if */
3201 } /* if */
3202 break;
3203 default:
3204 logError(printf("sqlBindBStri: Parameter " FMT_D " has the unknown type %s.\n",
3205 pos, nameOfSqlType(param->dataType)););
3206 err_info = RANGE_ERROR;
3207 break;
3208 } /* switch */
3209 if (likely(err_info == OKAY_NO_ERROR)) {
3210 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
3211 (SQLUSMALLINT) pos,
3212 SQL_PARAM_INPUT,
3213 c_type,
3214 param->dataType,
3215 param->paramSize,
3216 param->decimalDigits,
3217 param->buffer,
3218 (SQLLEN) param->buffer_length,
3219 ¶m->length) != SQL_SUCCESS)) {
3220 setDbErrorMsg("sqlBindBStri", "SQLBindParameter",
3221 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3222 logError(printf("sqlBindBStri: SQLBindParameter:\n%s\n",
3223 dbError.message););
3224 err_info = DATABASE_ERROR;
3225 } else {
3226 preparedStmt->fetchOkay = FALSE;
3227 param->bound = TRUE;
3228 } /* if */
3229 } /* if */
3230 } /* if */
3231 } /* if */
3232 if (unlikely(err_info != OKAY_NO_ERROR)) {
3233 raise_error(err_info);
3234 } /* if */
3235 } /* sqlBindBStri */
3236
3237
3238
sqlBindDuration(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second)3239 static void sqlBindDuration (sqlStmtType sqlStatement, intType pos,
3240 intType year, intType month, intType day, intType hour,
3241 intType minute, intType second, intType micro_second)
3242
3243 {
3244 preparedStmtType preparedStmt;
3245 bindDataType param;
3246 SQLSMALLINT c_type = 0;
3247 errInfoType err_info = OKAY_NO_ERROR;
3248
3249 /* sqlBindDuration */
3250 logFunction(printf("sqlBindDuration(" FMT_U_MEM ", " FMT_D ", P"
3251 FMT_D "Y" FMT_D "M" FMT_D "DT"
3252 FMT_D "H" FMT_D "M%s" FMT_U "." F_U(06) "S)\n",
3253 (memSizeType) sqlStatement, pos,
3254 year, month, day, hour, minute,
3255 second < 0 || micro_second < 0 ? "-" : "",
3256 intAbs(second), intAbs(micro_second)););
3257 preparedStmt = (preparedStmtType) sqlStatement;
3258 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3259 logError(printf("sqlBindDuration: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3260 pos, preparedStmt->param_array_size););
3261 err_info = RANGE_ERROR;
3262 } else if (unlikely(year < -INT_MAX || year > INT_MAX || month < -12 || month > 12 ||
3263 day < -31 || day > 31 || hour <= -24 || hour >= 24 ||
3264 minute <= -60 || minute >= 60 || second <= -60 || second >= 60 ||
3265 micro_second <= -1000000 || micro_second >= 1000000)) {
3266 logError(printf("sqlBindDuration: Duration not in allowed range.\n"););
3267 err_info = RANGE_ERROR;
3268 } else {
3269 if (preparedStmt->executeSuccessful) {
3270 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
3271 setDbErrorMsg("sqlBindDuration", "SQLFreeStmt",
3272 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3273 logError(printf("sqlBindDuration: SQLFreeStmt SQL_CLOSE:\n%s\n",
3274 dbError.message););
3275 err_info = DATABASE_ERROR;
3276 } else {
3277 preparedStmt->executeSuccessful = FALSE;
3278 freePrefetched(preparedStmt);
3279 } /* if */
3280 } /* if */
3281 if (likely(err_info == OKAY_NO_ERROR)) {
3282 param = &preparedStmt->param_array[pos - 1];
3283 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
3284 switch (param->dataType) {
3285 case SQL_VARCHAR:
3286 case SQL_LONGVARCHAR:
3287 if (param->buffer_capacity < sizeof(SQL_INTERVAL_STRUCT)) {
3288 free(param->buffer);
3289 if (unlikely((param->buffer = malloc(
3290 sizeof(SQL_INTERVAL_STRUCT))) == NULL)) {
3291 param->buffer_capacity = 0;
3292 err_info = MEMORY_ERROR;
3293 } else {
3294 param->buffer_capacity = sizeof(SQL_INTERVAL_STRUCT);
3295 } /* if */
3296 } /* if */
3297 if (likely(err_info == OKAY_NO_ERROR)) {
3298 param->buffer_length = sizeof(SQL_INTERVAL_STRUCT);
3299 c_type = assignToIntervalStruct((SQL_INTERVAL_STRUCT *)
3300 param->buffer,
3301 year, month, day, hour, minute, second, micro_second);
3302 if (unlikely(c_type == 0)) {
3303 logError(printf("sqlBindDuration(" FMT_U_MEM ", " FMT_D ", P"
3304 FMT_D "Y" FMT_D "M" FMT_D "DT"
3305 FMT_D "H" FMT_D "M%s" FMT_U "." F_U(06) "S): "
3306 "There is no adequate interval type.\n",
3307 (memSizeType) sqlStatement, pos,
3308 year, month, day, hour, minute,
3309 second < 0 || micro_second < 0 ? "-" : "",
3310 intAbs(second), intAbs(micro_second)););
3311 err_info = RANGE_ERROR;
3312 } /* if */
3313 } /* if */
3314 break;
3315 default:
3316 logError(printf("sqlBindDuration: Parameter " FMT_D " has the unknown type %s.\n",
3317 pos, nameOfSqlType(param->dataType)););
3318 err_info = RANGE_ERROR;
3319 break;
3320 } /* switch */
3321 if (likely(err_info == OKAY_NO_ERROR)) {
3322 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
3323 (SQLUSMALLINT) pos,
3324 SQL_PARAM_INPUT,
3325 c_type,
3326 param->dataType,
3327 param->paramSize,
3328 param->decimalDigits,
3329 param->buffer,
3330 (SQLLEN) param->buffer_length,
3331 NULL) != SQL_SUCCESS)) {
3332 setDbErrorMsg("sqlBindDuration", "SQLBindParameter",
3333 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3334 logError(printf("sqlBindDuration: SQLBindParameter:\n%s\n",
3335 dbError.message););
3336 err_info = DATABASE_ERROR;
3337 } else {
3338 preparedStmt->fetchOkay = FALSE;
3339 param->bound = TRUE;
3340 } /* if */
3341 } /* if */
3342 } /* if */
3343 } /* if */
3344 if (unlikely(err_info != OKAY_NO_ERROR)) {
3345 raise_error(err_info);
3346 } /* if */
3347 } /* sqlBindDuration */
3348
3349
3350
sqlBindFloat(sqlStmtType sqlStatement,intType pos,floatType value)3351 static void sqlBindFloat (sqlStmtType sqlStatement, intType pos, floatType value)
3352
3353 {
3354 preparedStmtType preparedStmt;
3355 bindDataType param;
3356 SQLSMALLINT c_type;
3357 errInfoType err_info = OKAY_NO_ERROR;
3358
3359 /* sqlBindFloat */
3360 logFunction(printf("sqlBindFloat(" FMT_U_MEM ", " FMT_D ", " FMT_E ")\n",
3361 (memSizeType) sqlStatement, pos, value););
3362 preparedStmt = (preparedStmtType) sqlStatement;
3363 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3364 logError(printf("sqlBindFloat: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3365 pos, preparedStmt->param_array_size););
3366 err_info = RANGE_ERROR;
3367 } else {
3368 if (preparedStmt->executeSuccessful) {
3369 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
3370 setDbErrorMsg("sqlBindFloat", "SQLFreeStmt",
3371 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3372 logError(printf("sqlBindFloat: SQLFreeStmt SQL_CLOSE:\n%s\n",
3373 dbError.message););
3374 err_info = DATABASE_ERROR;
3375 } else {
3376 preparedStmt->executeSuccessful = FALSE;
3377 freePrefetched(preparedStmt);
3378 } /* if */
3379 } /* if */
3380 if (likely(err_info == OKAY_NO_ERROR)) {
3381 param = &preparedStmt->param_array[pos - 1];
3382 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
3383 switch (param->dataType) {
3384 case SQL_REAL:
3385 c_type = SQL_C_FLOAT;
3386 *(float *) param->buffer = (float) value;
3387 break;
3388 case SQL_FLOAT:
3389 case SQL_DOUBLE:
3390 c_type = SQL_C_DOUBLE;
3391 *(double *) param->buffer = (double) value;
3392 break;
3393 case SQL_VARCHAR:
3394 case SQL_LONGVARCHAR:
3395 c_type = SQL_C_DOUBLE;
3396 if (param->buffer_capacity < sizeof(double)) {
3397 free(param->buffer);
3398 if (unlikely((param->buffer = malloc(sizeof(double))) == NULL)) {
3399 param->buffer_capacity = 0;
3400 err_info = MEMORY_ERROR;
3401 } else {
3402 param->buffer_capacity = sizeof(double);
3403 } /* if */
3404 } /* if */
3405 if (likely(err_info == OKAY_NO_ERROR)) {
3406 param->buffer_length = sizeof(double);
3407 *(double *) param->buffer = (double) value;
3408 } /* if */
3409 break;
3410 default:
3411 logError(printf("sqlBindFloat: Parameter " FMT_D " has the unknown type %s.\n",
3412 pos, nameOfSqlType(param->dataType)););
3413 err_info = RANGE_ERROR;
3414 break;
3415 } /* switch */
3416 if (likely(err_info == OKAY_NO_ERROR)) {
3417 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
3418 (SQLUSMALLINT) pos,
3419 SQL_PARAM_INPUT,
3420 c_type,
3421 param->dataType,
3422 param->paramSize,
3423 param->decimalDigits,
3424 param->buffer,
3425 (SQLLEN) param->buffer_length,
3426 NULL) != SQL_SUCCESS)) {
3427 setDbErrorMsg("sqlBindFloat", "SQLBindParameter",
3428 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3429 logError(printf("sqlBindFloat: SQLBindParameter:\n%s\n",
3430 dbError.message););
3431 err_info = DATABASE_ERROR;
3432 } else {
3433 preparedStmt->fetchOkay = FALSE;
3434 param->bound = TRUE;
3435 } /* if */
3436 } /* if */
3437 } /* if */
3438 } /* if */
3439 if (unlikely(err_info != OKAY_NO_ERROR)) {
3440 raise_error(err_info);
3441 } /* if */
3442 } /* sqlBindFloat */
3443
3444
3445
sqlBindInt(sqlStmtType sqlStatement,intType pos,intType value)3446 static void sqlBindInt (sqlStmtType sqlStatement, intType pos, intType value)
3447
3448 {
3449 preparedStmtType preparedStmt;
3450 bindDataType param;
3451 SQLSMALLINT c_type;
3452 errInfoType err_info = OKAY_NO_ERROR;
3453
3454 /* sqlBindInt */
3455 logFunction(printf("sqlBindInt(" FMT_U_MEM ", " FMT_D ", " FMT_D ")\n",
3456 (memSizeType) sqlStatement, pos, value););
3457 preparedStmt = (preparedStmtType) sqlStatement;
3458 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3459 logError(printf("sqlBindInt: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3460 pos, preparedStmt->param_array_size););
3461 err_info = RANGE_ERROR;
3462 } else {
3463 if (preparedStmt->executeSuccessful) {
3464 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
3465 setDbErrorMsg("sqlBindInt", "SQLFreeStmt",
3466 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3467 logError(printf("sqlBindInt: SQLFreeStmt SQL_CLOSE:\n%s\n",
3468 dbError.message););
3469 err_info = DATABASE_ERROR;
3470 } else {
3471 preparedStmt->executeSuccessful = FALSE;
3472 freePrefetched(preparedStmt);
3473 } /* if */
3474 } /* if */
3475 if (likely(err_info == OKAY_NO_ERROR)) {
3476 param = &preparedStmt->param_array[pos - 1];
3477 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
3478 switch (param->dataType) {
3479 case SQL_BIT:
3480 if (unlikely(value < 0 || value > 1)) {
3481 logError(printf("sqlBindInt: Parameter " FMT_D ": "
3482 FMT_D " does not fit into a bit.\n",
3483 pos, value));
3484 err_info = RANGE_ERROR;
3485 } else {
3486 c_type = SQL_C_BIT;
3487 *(char *) param->buffer = (char) value;
3488 } /* if */
3489 break;
3490 case SQL_TINYINT:
3491 if (preparedStmt->db->tinyintIsUnsigned) {
3492 if (unlikely(value < 0 || value > UINT8TYPE_MAX)) {
3493 logError(printf("sqlBindInt: Parameter " FMT_D ": "
3494 FMT_D " does not fit into a 8-bit unsigned integer.\n",
3495 pos, value));
3496 err_info = RANGE_ERROR;
3497 } else {
3498 c_type = SQL_C_UTINYINT;
3499 *(uint8Type *) param->buffer = (uint8Type) value;
3500 } /* if */
3501 } else {
3502 if (unlikely(value < INT8TYPE_MIN || value > INT8TYPE_MAX)) {
3503 logError(printf("sqlBindInt: Parameter " FMT_D ": "
3504 FMT_D " does not fit into a 8-bit signed integer.\n",
3505 pos, value));
3506 err_info = RANGE_ERROR;
3507 } else {
3508 c_type = SQL_C_STINYINT;
3509 *(int8Type *) param->buffer = (int8Type) value;
3510 } /* if */
3511 } /* if */
3512 break;
3513 case SQL_SMALLINT:
3514 if (unlikely(value < INT16TYPE_MIN || value > INT16TYPE_MAX)) {
3515 logError(printf("sqlBindInt: Parameter " FMT_D ": "
3516 FMT_D " does not fit into a 16-bit integer.\n",
3517 pos, value));
3518 err_info = RANGE_ERROR;
3519 } else {
3520 c_type = SQL_C_SSHORT;
3521 *(int16Type *) param->buffer = (int16Type) value;
3522 } /* if */
3523 break;
3524 case SQL_INTEGER:
3525 if (unlikely(value < INT32TYPE_MIN || value > INT32TYPE_MAX)) {
3526 logError(printf("sqlBindInt: Parameter " FMT_D ": "
3527 FMT_D " does not fit into a 32-bit integer.\n",
3528 pos, value));
3529 err_info = RANGE_ERROR;
3530 } else {
3531 c_type = SQL_C_SLONG;
3532 *(int32Type *) param->buffer = (int32Type) value;
3533 } /* if */
3534 break;
3535 case SQL_BIGINT:
3536 c_type = SQL_C_SBIGINT;
3537 *(int64Type *) param->buffer = value;
3538 break;
3539 case SQL_REAL:
3540 c_type = SQL_C_FLOAT;
3541 *(float *) param->buffer = (float) value;
3542 break;
3543 case SQL_FLOAT:
3544 case SQL_DOUBLE:
3545 c_type = SQL_C_DOUBLE;
3546 *(double *) param->buffer = (double) value;
3547 break;
3548 case SQL_DECIMAL:
3549 case SQL_NUMERIC:
3550 case SQL_CHAR:
3551 case SQL_VARCHAR:
3552 case SQL_LONGVARCHAR:
3553 c_type = SQL_C_SBIGINT;
3554 if (param->buffer_capacity < sizeof(int64Type)) {
3555 free(param->buffer);
3556 if (unlikely((param->buffer = malloc(sizeof(int64Type))) == NULL)) {
3557 param->buffer_capacity = 0;
3558 err_info = MEMORY_ERROR;
3559 } else {
3560 param->buffer_capacity = sizeof(int64Type);
3561 } /* if */
3562 } /* if */
3563 if (likely(err_info == OKAY_NO_ERROR)) {
3564 param->buffer_length = sizeof(int64Type);
3565 *(int64Type *) param->buffer = value;
3566 } /* if */
3567 break;
3568 default:
3569 logError(printf("sqlBindInt: Parameter " FMT_D " has the unknown type %s.\n",
3570 pos, nameOfSqlType(param->dataType)););
3571 err_info = RANGE_ERROR;
3572 break;
3573 } /* switch */
3574 if (likely(err_info == OKAY_NO_ERROR)) {
3575 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
3576 (SQLUSMALLINT) pos,
3577 SQL_PARAM_INPUT,
3578 c_type,
3579 param->dataType,
3580 param->paramSize,
3581 param->decimalDigits,
3582 param->buffer,
3583 (SQLLEN) param->buffer_length,
3584 NULL) != SQL_SUCCESS)) {
3585 setDbErrorMsg("sqlBindInt", "SQLBindParameter",
3586 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3587 logError(printf("sqlBindInt: SQLBindParameter:\n%s\n",
3588 dbError.message););
3589 err_info = DATABASE_ERROR;
3590 } else {
3591 preparedStmt->fetchOkay = FALSE;
3592 param->bound = TRUE;
3593 } /* if */
3594 } /* if */
3595 } /* if */
3596 } /* if */
3597 if (unlikely(err_info != OKAY_NO_ERROR)) {
3598 raise_error(err_info);
3599 } /* if */
3600 } /* sqlBindInt */
3601
3602
3603
sqlBindNull(sqlStmtType sqlStatement,intType pos)3604 static void sqlBindNull (sqlStmtType sqlStatement, intType pos)
3605
3606 {
3607 preparedStmtType preparedStmt;
3608 bindDataType param;
3609 errInfoType err_info = OKAY_NO_ERROR;
3610
3611 /* sqlBindNull */
3612 logFunction(printf("sqlBindNull(" FMT_U_MEM ", " FMT_D ")\n",
3613 (memSizeType) sqlStatement, pos););
3614 preparedStmt = (preparedStmtType) sqlStatement;
3615 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3616 logError(printf("sqlBindNull: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3617 pos, preparedStmt->param_array_size););
3618 raise_error(RANGE_ERROR);
3619 } else {
3620 if (preparedStmt->executeSuccessful) {
3621 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
3622 setDbErrorMsg("sqlBindNull", "SQLFreeStmt",
3623 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3624 logError(printf("sqlBindNull: SQLFreeStmt SQL_CLOSE:\n%s\n",
3625 dbError.message););
3626 err_info = DATABASE_ERROR;
3627 } else {
3628 preparedStmt->executeSuccessful = FALSE;
3629 freePrefetched(preparedStmt);
3630 } /* if */
3631 } /* if */
3632 if (unlikely(err_info != OKAY_NO_ERROR)) {
3633 raise_error(err_info);
3634 } else {
3635 param = &preparedStmt->param_array[pos - 1];
3636 param->length = SQL_NULL_DATA;
3637 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
3638 (SQLUSMALLINT) pos,
3639 SQL_PARAM_INPUT,
3640 SQL_C_CHAR,
3641 param->dataType,
3642 param->paramSize,
3643 param->decimalDigits,
3644 NULL,
3645 0,
3646 ¶m->length) != SQL_SUCCESS)) {
3647 setDbErrorMsg("sqlBindNull", "SQLBindParameter",
3648 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3649 logError(printf("sqlBindNull: SQLBindParameter:\n%s\n",
3650 dbError.message););
3651 raise_error(DATABASE_ERROR);
3652 } else {
3653 preparedStmt->fetchOkay = FALSE;
3654 param->bound = TRUE;
3655 } /* if */
3656 } /* if */
3657 } /* if */
3658 } /* sqlBindNull */
3659
3660
3661
sqlBindStri(sqlStmtType sqlStatement,intType pos,const const_striType stri)3662 static void sqlBindStri (sqlStmtType sqlStatement, intType pos,
3663 const const_striType stri)
3664
3665 {
3666 preparedStmtType preparedStmt;
3667 bindDataType param;
3668 SQLSMALLINT c_type;
3669 wstriType wstri;
3670 memSizeType length;
3671 errInfoType err_info = OKAY_NO_ERROR;
3672
3673 /* sqlBindStri */
3674 logFunction(printf("sqlBindStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
3675 (memSizeType) sqlStatement, pos, striAsUnquotedCStri(stri)););
3676 preparedStmt = (preparedStmtType) sqlStatement;
3677 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3678 logError(printf("sqlBindStri: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3679 pos, preparedStmt->param_array_size););
3680 err_info = RANGE_ERROR;
3681 } else {
3682 if (preparedStmt->executeSuccessful) {
3683 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
3684 setDbErrorMsg("sqlBindStri", "SQLFreeStmt",
3685 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3686 logError(printf("sqlBindStri: SQLFreeStmt SQL_CLOSE:\n%s\n",
3687 dbError.message););
3688 err_info = DATABASE_ERROR;
3689 } else {
3690 preparedStmt->executeSuccessful = FALSE;
3691 freePrefetched(preparedStmt);
3692 } /* if */
3693 } /* if */
3694 if (likely(err_info == OKAY_NO_ERROR)) {
3695 param = &preparedStmt->param_array[pos - 1];
3696 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
3697 switch (param->dataType) {
3698 case SQL_CHAR:
3699 case SQL_VARCHAR:
3700 case SQL_LONGVARCHAR:
3701 case SQL_WCHAR:
3702 case SQL_WVARCHAR:
3703 case SQL_WLONGVARCHAR:
3704 case SQL_CLOB:
3705 c_type = SQL_C_WCHAR;
3706 if (unlikely(stri->size > MAX_WSTRI_LEN / SURROGATE_PAIR_FACTOR)) {
3707 /* It is not possible to compute the memory size. */
3708 err_info = MEMORY_ERROR;
3709 } else {
3710 if (param->buffer_capacity < SIZ_WSTRI(SURROGATE_PAIR_FACTOR * stri->size)) {
3711 free(param->buffer);
3712 if (unlikely(!ALLOC_WSTRI(param->buffer, SURROGATE_PAIR_FACTOR * stri->size))) {
3713 param->buffer_capacity = 0;
3714 err_info = MEMORY_ERROR;
3715 } else {
3716 param->buffer_capacity = SIZ_WSTRI(SURROGATE_PAIR_FACTOR * stri->size);
3717 } /* if */
3718 } /* if */
3719 if (likely(err_info == OKAY_NO_ERROR)) {
3720 wstri = (wstriType) param->buffer;
3721 length = stri_to_utf16(wstri, stri->mem, stri->size, &err_info);
3722 wstri[length] = '\0';
3723 if (likely(err_info == OKAY_NO_ERROR)) {
3724 if (unlikely(length > SQLLEN_MAX >> 1)) {
3725 /* It is not possible to cast length << 1 to SQLLEN. */
3726 free(param->buffer);
3727 param->buffer = NULL;
3728 param->buffer_capacity = 0;
3729 err_info = MEMORY_ERROR;
3730 } else {
3731 param->buffer_length = length << 1;
3732 param->length = (SQLLEN) (length << 1);
3733 } /* if */
3734 } /* if */
3735 } /* if */
3736 } /* if */
3737 break;
3738 default:
3739 logError(printf("sqlBindStri: Parameter " FMT_D " has the unknown type %s.\n",
3740 pos, nameOfSqlType(param->dataType)););
3741 err_info = RANGE_ERROR;
3742 break;
3743 } /* switch */
3744 if (likely(err_info == OKAY_NO_ERROR)) {
3745 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
3746 (SQLUSMALLINT) pos,
3747 SQL_PARAM_INPUT,
3748 c_type,
3749 param->dataType,
3750 param->paramSize,
3751 param->decimalDigits,
3752 param->buffer,
3753 (SQLLEN) param->buffer_length,
3754 ¶m->length) != SQL_SUCCESS)) {
3755 setDbErrorMsg("sqlBindStri", "SQLBindParameter",
3756 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3757 logError(printf("sqlBindStri: SQLBindParameter:\n%s\n",
3758 dbError.message););
3759 err_info = DATABASE_ERROR;
3760 } else {
3761 preparedStmt->fetchOkay = FALSE;
3762 param->bound = TRUE;
3763 } /* if */
3764 } /* if */
3765 } /* if */
3766 } /* if */
3767 if (unlikely(err_info != OKAY_NO_ERROR)) {
3768 raise_error(err_info);
3769 } /* if */
3770 } /* sqlBindStri */
3771
3772
3773
sqlBindTime(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second,intType time_zone)3774 static void sqlBindTime (sqlStmtType sqlStatement, intType pos,
3775 intType year, intType month, intType day, intType hour,
3776 intType minute, intType second, intType micro_second,
3777 intType time_zone)
3778
3779 {
3780 preparedStmtType preparedStmt;
3781 bindDataType param;
3782 SQLSMALLINT c_type;
3783 SQL_DATE_STRUCT *dateValue;
3784 SQL_TIME_STRUCT *timeValue;
3785 SQL_TIMESTAMP_STRUCT *timestampValue;
3786 char *datetime2;
3787 intType fraction;
3788 errInfoType err_info = OKAY_NO_ERROR;
3789
3790 /* sqlBindTime */
3791 logFunction(printf("sqlBindTime(" FMT_U_MEM ", " FMT_D ", "
3792 F_D(04) "-" F_D(02) "-" F_D(02) " "
3793 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ", "
3794 FMT_D ")\n",
3795 (memSizeType) sqlStatement, pos,
3796 year, month, day,
3797 hour, minute, second, micro_second,
3798 time_zone););
3799 preparedStmt = (preparedStmtType) sqlStatement;
3800 if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3801 logError(printf("sqlBindTime: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3802 pos, preparedStmt->param_array_size););
3803 err_info = RANGE_ERROR;
3804 } else if (unlikely(year < SHRT_MIN || year > SHRT_MAX || month < 1 || month > 12 ||
3805 day < 1 || day > 31 || hour < 0 || hour >= 24 ||
3806 minute < 0 || minute >= 60 || second < 0 || second >= 60 ||
3807 micro_second < 0 || micro_second >= 1000000)) {
3808 logError(printf("sqlBindTime: Time not in allowed range.\n"););
3809 err_info = RANGE_ERROR;
3810 } else {
3811 if (preparedStmt->executeSuccessful) {
3812 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
3813 setDbErrorMsg("sqlBindTime", "SQLFreeStmt",
3814 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3815 logError(printf("sqlBindTime: SQLFreeStmt SQL_CLOSE:\n%s\n",
3816 dbError.message););
3817 err_info = DATABASE_ERROR;
3818 } else {
3819 preparedStmt->executeSuccessful = FALSE;
3820 freePrefetched(preparedStmt);
3821 } /* if */
3822 } /* if */
3823 if (likely(err_info == OKAY_NO_ERROR)) {
3824 param = &preparedStmt->param_array[pos - 1];
3825 /* printf("paramType: %s\n", nameOfSqlType(param->dataType)); */
3826 switch (param->dataType) {
3827 case SQL_TYPE_DATE:
3828 c_type = SQL_C_TYPE_DATE;
3829 dateValue = (SQL_DATE_STRUCT *) param->buffer;
3830 dateValue->year = (SQLSMALLINT) year;
3831 dateValue->month = (SQLUSMALLINT) month;
3832 dateValue->day = (SQLUSMALLINT) day;
3833 break;
3834 case SQL_TYPE_TIME:
3835 c_type = SQL_C_TYPE_TIME;
3836 timeValue = (SQL_TIME_STRUCT *) param->buffer;
3837 timeValue->hour = (SQLUSMALLINT) hour;
3838 timeValue->minute = (SQLUSMALLINT) minute;
3839 timeValue->second = (SQLUSMALLINT) second;
3840 break;
3841 case SQL_DATETIME:
3842 case SQL_TYPE_TIMESTAMP:
3843 c_type = SQL_C_TYPE_TIMESTAMP;
3844 switch (param->decimalDigits) {
3845 case 0: fraction = 0; break;
3846 case 1: fraction = micro_second / 100000 * 100000000; break;
3847 case 2: fraction = micro_second / 10000 * 10000000; break;
3848 case 3: fraction = micro_second / 1000 * 1000000; break;
3849 case 4: fraction = micro_second / 100 * 100000; break;
3850 case 5: fraction = micro_second / 10 * 10000; break;
3851 default: fraction = micro_second * 1000; break;
3852 } /* switch */
3853 timestampValue = (SQL_TIMESTAMP_STRUCT *) param->buffer;
3854 timestampValue->year = (SQLSMALLINT) year;
3855 timestampValue->month = (SQLUSMALLINT) month;
3856 timestampValue->day = (SQLUSMALLINT) day;
3857 timestampValue->hour = (SQLUSMALLINT) hour;
3858 timestampValue->minute = (SQLUSMALLINT) minute;
3859 timestampValue->second = (SQLUSMALLINT) second;
3860 timestampValue->fraction = (SQLUINTEGER) fraction;
3861 /* printf("fraction: %lu\n", (unsigned long) timestampValue->fraction); */
3862 break;
3863 case SQL_WVARCHAR:
3864 case SQL_VARCHAR:
3865 case SQL_LONGVARCHAR:
3866 c_type = SQL_C_CHAR;
3867 if (param->buffer_capacity < SIZ_CSTRI(MAX_DATETIME2_LENGTH)) {
3868 free(param->buffer);
3869 if (unlikely((param->buffer = malloc(
3870 SIZ_CSTRI(MAX_DATETIME2_LENGTH))) == NULL)) {
3871 param->buffer_capacity = 0;
3872 err_info = MEMORY_ERROR;
3873 } else {
3874 param->buffer_capacity = SIZ_CSTRI(MAX_DATETIME2_LENGTH);
3875 } /* if */
3876 } /* if */
3877 if (unlikely(year < -999 || year > 9999)) {
3878 logError(printf("sqlBindTime: Year not in allowed range.\n"););
3879 err_info = RANGE_ERROR;
3880 } /* if */
3881 if (likely(err_info == OKAY_NO_ERROR)) {
3882 datetime2 = (char *) param->buffer;
3883 /* printf("paramSize: " FMT_U_MEM "\n", param->paramSize); */
3884 if (param->paramSize == 10 && hour == 0 && minute == 0 &&
3885 second == 0 && micro_second == 0 &&
3886 (year != 0 || month != 1 || day != 1)) {
3887 sprintf(datetime2, F_D(04) "-" F_D(02) "-" F_D(02),
3888 year, month, day);
3889 } else if (param->paramSize >= 8 &&
3890 year == 0 && month == 1 && day == 1) {
3891 sprintf(datetime2, F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(07),
3892 hour, minute, second, micro_second * 10);
3893 } else if (param->paramSize >= 19) {
3894 sprintf(datetime2, F_D(04) "-" F_D(02) "-" F_D(02) " "
3895 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(07),
3896 year, month, day,
3897 hour, minute, second, micro_second * 10);
3898 } else {
3899 err_info = RANGE_ERROR;
3900 } /* if */
3901 /* printf("datetime2: %s\n", datetime2); */
3902 datetime2[param->paramSize] = '\0';
3903 /* printf("datetime2: %s\n", datetime2); */
3904 param->buffer_length = (memSizeType) param->paramSize;
3905 /* printf("buffer_length: " FMT_U_MEM "\n", param->buffer_length); */
3906 } /* if */
3907 break;
3908 default:
3909 logError(printf("sqlBindTime: Parameter " FMT_D " has the unknown type %s.\n",
3910 pos, nameOfSqlType(param->dataType)););
3911 err_info = RANGE_ERROR;
3912 break;
3913 } /* switch */
3914 if (likely(err_info == OKAY_NO_ERROR)) {
3915 /* printf("paramSize: " FMT_U_MEM "\n", (long) param->paramSize); */
3916 /* printf("decimalDigits: " FMT_D16 "\n", param->decimalDigits); */
3917 if (unlikely(SQLBindParameter(preparedStmt->ppStmt,
3918 (SQLUSMALLINT) pos,
3919 SQL_PARAM_INPUT,
3920 c_type,
3921 param->dataType,
3922 param->paramSize,
3923 param->decimalDigits,
3924 param->buffer,
3925 (SQLLEN) param->buffer_length,
3926 NULL) != SQL_SUCCESS)) {
3927 setDbErrorMsg("sqlBindTime", "SQLBindParameter",
3928 SQL_HANDLE_STMT, preparedStmt->ppStmt);
3929 logError(printf("sqlBindTime: SQLBindParameter:\n%s\n",
3930 dbError.message););
3931 err_info = DATABASE_ERROR;
3932 } else {
3933 preparedStmt->fetchOkay = FALSE;
3934 param->bound = TRUE;
3935 } /* if */
3936 } /* if */
3937 } /* if */
3938 } /* if */
3939 if (unlikely(err_info != OKAY_NO_ERROR)) {
3940 raise_error(err_info);
3941 } /* if */
3942 } /* sqlBindTime */
3943
3944
3945
sqlClose(databaseType database)3946 static void sqlClose (databaseType database)
3947
3948 {
3949 dbType db;
3950
3951 /* sqlClose */
3952 logFunction(printf("sqlClose(" FMT_U_MEM ")\n",
3953 (memSizeType) database););
3954 db = (dbType) database;
3955 if (db->connection != SQL_NULL_HANDLE) {
3956 SQLDisconnect(db->connection);
3957 SQLFreeHandle(SQL_HANDLE_DBC, db->connection);
3958 db->connection = SQL_NULL_HANDLE;
3959 } /* if */
3960 if (db->sql_environment != SQL_NULL_HANDLE) {
3961 SQLFreeHandle(SQL_HANDLE_ENV, db->sql_environment);
3962 db->sql_environment = SQL_NULL_HANDLE;
3963 } /* if */
3964 logFunction(printf("sqlClose -->\n"););
3965 } /* sqlClose */
3966
3967
3968
sqlColumnBigInt(sqlStmtType sqlStatement,intType column)3969 static bigIntType sqlColumnBigInt (sqlStmtType sqlStatement, intType column)
3970
3971 {
3972 preparedStmtType preparedStmt;
3973 resultDescrType columnDescr;
3974 resultDataType columnData;
3975 bigIntType columnValue;
3976
3977 /* sqlColumnBigInt */
3978 logFunction(printf("sqlColumnBigInt(" FMT_U_MEM ", " FMT_D ")\n",
3979 (memSizeType) sqlStatement, column););
3980 preparedStmt = (preparedStmtType) sqlStatement;
3981 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3982 (uintType) column > preparedStmt->result_array_size)) {
3983 logError(printf("sqlColumnBigInt: Fetch okay: %d, column: " FMT_D
3984 ", max column: " FMT_U_MEM ".\n",
3985 preparedStmt->fetchOkay, column,
3986 preparedStmt->result_array_size););
3987 raise_error(RANGE_ERROR);
3988 columnValue = NULL;
3989 } else {
3990 columnDescr = &preparedStmt->result_descr_array[column - 1];
3991 columnData = &preparedStmt->currentFetch->result_array[column - 1];
3992 if (columnData->length == SQL_NULL_DATA) {
3993 /* printf("Column is NULL -> Use default value: 0\n"); */
3994 columnValue = bigZero();
3995 } else if (unlikely(columnData->length < 0)) {
3996 dbInconsistent("sqlColumnBigInt", "SQLBindCol");
3997 logError(printf("sqlColumnBigInt: Column " FMT_D ": "
3998 "Negative length: " FMT_D_LEN "\n",
3999 column, columnData->length););
4000 raise_error(DATABASE_ERROR);
4001 columnValue = NULL;
4002 } else if (unlikely(!columnDescr->sql_data_at_exec &&
4003 (SQLULEN) columnData->length > columnDescr->buffer_length)) {
4004 dbInconsistent("sqlColumnBigInt", "SQLBindCol");
4005 logError(printf("sqlColumnBigInt: Column " FMT_D ": Length (" FMT_D_LEN
4006 ") greater than buffer_length (" FMT_U_MEM ").\n",
4007 column, columnData->length,
4008 columnDescr->buffer_length););
4009 raise_error(DATABASE_ERROR);
4010 columnValue = NULL;
4011 } else {
4012 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4013 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4014 switch (columnDescr->dataType) {
4015 case SQL_BIT:
4016 columnValue = bigFromInt32((int32Type)
4017 (*(char *) columnData->buffer) != 0);
4018 break;
4019 case SQL_TINYINT:
4020 /* SQL_TINYINT can be signed or unsigned. */
4021 /* We use a c_type of SQL_C_SSHORT to be on the safe side. */
4022 case SQL_SMALLINT:
4023 columnValue = bigFromInt32((int32Type)
4024 *(int16Type *) columnData->buffer);
4025 break;
4026 case SQL_INTEGER:
4027 columnValue = bigFromInt32(
4028 *(int32Type *) columnData->buffer);
4029 break;
4030 case SQL_BIGINT:
4031 columnValue = bigFromInt64(
4032 *(int64Type *) columnData->buffer);
4033 break;
4034 case SQL_DECIMAL:
4035 columnValue = getDecimalBigInt(
4036 (const_ustriType) columnData->buffer,
4037 (memSizeType) columnData->length);
4038 break;
4039 case SQL_NUMERIC:
4040 columnValue = getBigInt(columnData->buffer,
4041 (memSizeType) columnData->length);
4042 break;
4043 default:
4044 logError(printf("sqlColumnBigInt: Column " FMT_D " has the unknown type %s.\n",
4045 column, nameOfSqlType(columnDescr->dataType)););
4046 raise_error(RANGE_ERROR);
4047 columnValue = NULL;
4048 break;
4049 } /* switch */
4050 } /* if */
4051 } /* if */
4052 logFunction(printf("sqlColumnBigInt --> %s\n", bigHexCStri(columnValue)););
4053 return columnValue;
4054 } /* sqlColumnBigInt */
4055
4056
4057
sqlColumnBigRat(sqlStmtType sqlStatement,intType column,bigIntType * numerator,bigIntType * denominator)4058 static void sqlColumnBigRat (sqlStmtType sqlStatement, intType column,
4059 bigIntType *numerator, bigIntType *denominator)
4060
4061 {
4062 preparedStmtType preparedStmt;
4063 resultDescrType columnDescr;
4064 resultDataType columnData;
4065 float floatValue;
4066 double doubleValue;
4067
4068 /* sqlColumnBigRat */
4069 logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", *, *)\n",
4070 (memSizeType) sqlStatement, column););
4071 preparedStmt = (preparedStmtType) sqlStatement;
4072 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4073 (uintType) column > preparedStmt->result_array_size)) {
4074 logError(printf("sqlColumnBigRat: Fetch okay: %d, column: " FMT_D
4075 ", max column: " FMT_U_MEM ".\n",
4076 preparedStmt->fetchOkay, column,
4077 preparedStmt->result_array_size););
4078 raise_error(RANGE_ERROR);
4079 } else {
4080 columnDescr = &preparedStmt->result_descr_array[column - 1];
4081 columnData = &preparedStmt->currentFetch->result_array[column - 1];
4082 if (columnData->length == SQL_NULL_DATA) {
4083 /* printf("Column is NULL -> Use default value: 0\n"); */
4084 *numerator = bigZero();
4085 *denominator = bigFromInt32(1);
4086 } else if (unlikely(columnData->length < 0)) {
4087 dbInconsistent("sqlColumnBigRat", "SQLBindCol");
4088 logError(printf("sqlColumnBigRat: Column " FMT_D ": "
4089 "Negative length: " FMT_D_LEN "\n",
4090 column, columnData->length););
4091 raise_error(DATABASE_ERROR);
4092 } else if (unlikely(!columnDescr->sql_data_at_exec &&
4093 (SQLULEN) columnData->length > columnDescr->buffer_length)) {
4094 dbInconsistent("sqlColumnBigRat", "SQLBindCol");
4095 logError(printf("sqlColumnBigRat: Column " FMT_D ": Length (" FMT_D_LEN
4096 ") greater than buffer_length (" FMT_U_MEM ").\n",
4097 column, columnData->length,
4098 columnDescr->buffer_length););
4099 raise_error(DATABASE_ERROR);
4100 } else {
4101 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4102 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4103 switch (columnDescr->dataType) {
4104 case SQL_BIT:
4105 *numerator = bigFromInt32((int32Type)
4106 (*(char *) columnData->buffer) != 0);
4107 *denominator = bigFromInt32(1);
4108 break;
4109 case SQL_TINYINT:
4110 /* SQL_TINYINT can be signed or unsigned. */
4111 /* We use a c_type of SQL_C_SSHORT to be on the safe side. */
4112 case SQL_SMALLINT:
4113 *numerator = bigFromInt32((int32Type)
4114 *(int16Type *) columnData->buffer);
4115 *denominator = bigFromInt32(1);
4116 break;
4117 case SQL_INTEGER:
4118 *numerator = bigFromInt32(
4119 *(int32Type *) columnData->buffer);
4120 *denominator = bigFromInt32(1);
4121 break;
4122 case SQL_BIGINT:
4123 *numerator = bigFromInt64(
4124 *(int64Type *) columnData->buffer);
4125 *denominator = bigFromInt32(1);
4126 break;
4127 case SQL_REAL:
4128 floatValue = *(float *) columnData->buffer;
4129 /* printf("sqlColumnBigRat: float: %f\n", floatValue); */
4130 *numerator = roundDoubleToBigRat(floatValue, FALSE, denominator);
4131 break;
4132 case SQL_FLOAT:
4133 case SQL_DOUBLE:
4134 doubleValue = *(double *) columnData->buffer;
4135 /* printf("sqlColumnBigRat: double: %f\n", doubleValue); */
4136 *numerator = roundDoubleToBigRat(doubleValue, TRUE, denominator);
4137 break;
4138 case SQL_DECIMAL:
4139 *numerator = getDecimalBigRational((const_ustriType) columnData->buffer,
4140 (memSizeType) columnData->length, denominator);
4141 break;
4142 case SQL_NUMERIC:
4143 *numerator = getBigRational(columnData->buffer,
4144 (memSizeType) columnData->length, denominator);
4145 break;
4146 default:
4147 logError(printf("sqlColumnBigRat: Column " FMT_D " has the unknown type %s.\n",
4148 column, nameOfSqlType(columnDescr->dataType)););
4149 raise_error(RANGE_ERROR);
4150 break;
4151 } /* switch */
4152 } /* if */
4153 } /* if */
4154 logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s) -->\n",
4155 (memSizeType) sqlStatement, column,
4156 bigHexCStri(*numerator), bigHexCStri(*denominator)););
4157 } /* sqlColumnBigRat */
4158
4159
4160
sqlColumnBool(sqlStmtType sqlStatement,intType column)4161 static boolType sqlColumnBool (sqlStmtType sqlStatement, intType column)
4162
4163 {
4164 preparedStmtType preparedStmt;
4165 resultDescrType columnDescr;
4166 resultDataType columnData;
4167 intType columnValue;
4168
4169 /* sqlColumnBool */
4170 logFunction(printf("sqlColumnBool(" FMT_U_MEM ", " FMT_D ")\n",
4171 (memSizeType) sqlStatement, column););
4172 preparedStmt = (preparedStmtType) sqlStatement;
4173 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4174 (uintType) column > preparedStmt->result_array_size)) {
4175 logError(printf("sqlColumnBool: Fetch okay: %d, column: " FMT_D
4176 ", max column: " FMT_U_MEM ".\n",
4177 preparedStmt->fetchOkay, column,
4178 preparedStmt->result_array_size););
4179 raise_error(RANGE_ERROR);
4180 columnValue = 0;
4181 } else {
4182 columnDescr = &preparedStmt->result_descr_array[column - 1];
4183 columnData = &preparedStmt->currentFetch->result_array[column - 1];
4184 if (columnData->length == SQL_NULL_DATA) {
4185 /* printf("Column is NULL -> Use default value: FALSE\n"); */
4186 columnValue = 0;
4187 } else if (unlikely(columnData->length < 0)) {
4188 dbInconsistent("sqlColumnBool", "SQLBindCol");
4189 logError(printf("sqlColumnBool: Column " FMT_D ": "
4190 "Negative length: " FMT_D_LEN "\n",
4191 column, columnData->length););
4192 raise_error(DATABASE_ERROR);
4193 columnValue = 0;
4194 } else {
4195 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4196 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4197 /* printf("c_type: %s\n", nameOfCType(columnDescr->c_type)); */
4198 switch (columnDescr->dataType) {
4199 case SQL_CHAR:
4200 case SQL_VARCHAR:
4201 case SQL_LONGVARCHAR:
4202 case SQL_WCHAR:
4203 case SQL_WVARCHAR:
4204 case SQL_WLONGVARCHAR:
4205 switch (columnDescr->c_type) {
4206 case SQL_C_CHAR:
4207 if (unlikely(columnData->length != 1)) {
4208 logError(printf("sqlColumnBool: Column " FMT_D ": "
4209 "The size of a boolean field must be 1.\n", column););
4210 raise_error(RANGE_ERROR);
4211 columnValue = 0;
4212 } else {
4213 columnValue = *(const_cstriType) columnData->buffer - '0';
4214 } /* if */
4215 break;
4216 case SQL_C_WCHAR:
4217 if (unlikely(columnData->length != 2)) {
4218 logError(printf("sqlColumnBool: Column " FMT_D ": "
4219 "The size of a boolean field must be 1.\n", column););
4220 raise_error(RANGE_ERROR);
4221 columnValue = 0;
4222 } else {
4223 columnValue = *(const_wstriType) columnData->buffer - '0';
4224 } /* if */
4225 break;
4226 default:
4227 logError(printf("sqlColumnBool: Column " FMT_D " has the unknown C type %s.\n",
4228 column, nameOfCType(columnDescr->c_type)););
4229 raise_error(RANGE_ERROR);
4230 columnValue = 0;
4231 break;
4232 } /* switch */
4233 break;
4234 case SQL_BIT:
4235 columnValue = *(char *) columnData->buffer;
4236 break;
4237 case SQL_TINYINT:
4238 /* SQL_TINYINT can be signed or unsigned. */
4239 /* We use a c_type of SQL_C_SSHORT to be on the safe side. */
4240 case SQL_SMALLINT:
4241 columnValue = *(int16Type *) columnData->buffer;
4242 break;
4243 case SQL_INTEGER:
4244 columnValue = *(int32Type *) columnData->buffer;
4245 break;
4246 case SQL_BIGINT:
4247 columnValue = *(int64Type *) columnData->buffer;
4248 break;
4249 case SQL_DECIMAL:
4250 columnValue = getDecimalInt(
4251 (const_ustriType) columnData->buffer,
4252 (memSizeType) columnData->length);
4253 break;
4254 case SQL_NUMERIC:
4255 columnValue = getInt(
4256 columnData->buffer,
4257 (memSizeType) columnData->length);
4258 break;
4259 default:
4260 logError(printf("sqlColumnBool: Column " FMT_D " has the unknown type %s.\n",
4261 column, nameOfSqlType(columnDescr->dataType)););
4262 raise_error(RANGE_ERROR);
4263 columnValue = 0;
4264 break;
4265 } /* switch */
4266 if (unlikely((uintType) columnValue >= 2)) {
4267 logError(printf("sqlColumnBool: Column " FMT_D ": "
4268 FMT_D " is not an allowed boolean value.\n",
4269 column, columnValue););
4270 raise_error(RANGE_ERROR);
4271 } /* if */
4272 } /* if */
4273 } /* if */
4274 logFunction(printf("sqlColumnBool --> %s\n", columnValue ? "TRUE" : "FALSE"););
4275 return columnValue != 0;
4276 } /* sqlColumnBool */
4277
4278
4279
sqlColumnBStri(sqlStmtType sqlStatement,intType column)4280 static bstriType sqlColumnBStri (sqlStmtType sqlStatement, intType column)
4281
4282 {
4283 preparedStmtType preparedStmt;
4284 resultDescrType columnDescr;
4285 resultDataType columnData;
4286 memSizeType length;
4287 bstriType columnValue;
4288
4289 /* sqlColumnBStri */
4290 logFunction(printf("sqlColumnBStri(" FMT_U_MEM ", " FMT_D ")\n",
4291 (memSizeType) sqlStatement, column););
4292 preparedStmt = (preparedStmtType) sqlStatement;
4293 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4294 (uintType) column > preparedStmt->result_array_size)) {
4295 logError(printf("sqlColumnBStri: Fetch okay: %d, column: " FMT_D
4296 ", max column: " FMT_U_MEM ".\n",
4297 preparedStmt->fetchOkay, column,
4298 preparedStmt->result_array_size););
4299 raise_error(RANGE_ERROR);
4300 columnValue = NULL;
4301 } else {
4302 columnDescr = &preparedStmt->result_descr_array[column - 1];
4303 columnData = &preparedStmt->currentFetch->result_array[column - 1];
4304 if (columnData->length == SQL_NULL_DATA) {
4305 /* printf("Column is NULL -> Use default value: \"\"\n"); */
4306 if (unlikely(!ALLOC_BSTRI_SIZE_OK(columnValue, 0))) {
4307 raise_error(MEMORY_ERROR);
4308 } else {
4309 columnValue->size = 0;
4310 } /* if */
4311 } else if (unlikely(columnData->length < 0)) {
4312 dbInconsistent("sqlColumnBStri", "SQLBindCol");
4313 logError(printf("sqlColumnBStri: Column " FMT_D ": "
4314 "Negative length: " FMT_D_LEN "\n",
4315 column, columnData->length););
4316 raise_error(DATABASE_ERROR);
4317 columnValue = NULL;
4318 } else if (unlikely(!columnDescr->sql_data_at_exec &&
4319 (SQLULEN) columnData->length > columnDescr->buffer_length)) {
4320 dbInconsistent("sqlColumnBStri", "SQLBindCol");
4321 logError(printf("sqlColumnBStri: Column " FMT_D ": Length (" FMT_D_LEN
4322 ") greater than buffer_length (" FMT_U_MEM ").\n",
4323 column, columnData->length,
4324 columnDescr->buffer_length););
4325 raise_error(DATABASE_ERROR);
4326 columnValue = NULL;
4327 } else {
4328 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4329 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4330 switch (columnDescr->dataType) {
4331 case SQL_BINARY:
4332 case SQL_VARBINARY:
4333 case SQL_LONGVARBINARY:
4334 /* This might be a blob, which is filled by fetchBlobs(). */
4335 length = (memSizeType) columnData->length;
4336 if (unlikely(!ALLOC_BSTRI_CHECK_SIZE(columnValue, length))) {
4337 raise_error(MEMORY_ERROR);
4338 } else {
4339 columnValue->size = length;
4340 memcpy(columnValue->mem,
4341 (ustriType) columnData->buffer,
4342 length);
4343 } /* if */
4344 break;
4345 default:
4346 logError(printf("sqlColumnBStri: Column " FMT_D " has the unknown type %s.\n",
4347 column, nameOfSqlType(columnDescr->dataType)););
4348 raise_error(RANGE_ERROR);
4349 columnValue = NULL;
4350 break;
4351 } /* switch */
4352 } /* if */
4353 } /* if */
4354 logFunction(printf("sqlColumnBStri --> \"%s\"\n", bstriAsUnquotedCStri(columnValue)););
4355 return columnValue;
4356 } /* sqlColumnBStri */
4357
4358
4359
sqlColumnDuration(sqlStmtType sqlStatement,intType column,intType * year,intType * month,intType * day,intType * hour,intType * minute,intType * second,intType * micro_second)4360 static void sqlColumnDuration (sqlStmtType sqlStatement, intType column,
4361 intType *year, intType *month, intType *day, intType *hour,
4362 intType *minute, intType *second, intType *micro_second)
4363
4364 {
4365 preparedStmtType preparedStmt;
4366 resultDescrType columnDescr;
4367 resultDataType columnData;
4368 SQL_INTERVAL_STRUCT *interval;
4369 memSizeType length;
4370 char duration[MAX_DURATION_LENGTH + NULL_TERMINATION_LEN];
4371 errInfoType err_info = OKAY_NO_ERROR;
4372
4373 /* sqlColumnDuration */
4374 logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ", *)\n",
4375 (memSizeType) sqlStatement, column););
4376 preparedStmt = (preparedStmtType) sqlStatement;
4377 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4378 (uintType) column > preparedStmt->result_array_size)) {
4379 logError(printf("sqlColumnDuration: Fetch okay: %d, column: " FMT_D
4380 ", max column: " FMT_U_MEM ".\n",
4381 preparedStmt->fetchOkay, column,
4382 preparedStmt->result_array_size););
4383 raise_error(RANGE_ERROR);
4384 } else {
4385 columnDescr = &preparedStmt->result_descr_array[column - 1];
4386 columnData = &preparedStmt->currentFetch->result_array[column - 1];
4387 if (columnData->length == SQL_NULL_DATA) {
4388 /* printf("Column is NULL -> Use default value: P0D\n"); */
4389 *year = 0;
4390 *month = 0;
4391 *day = 0;
4392 *hour = 0;
4393 *minute = 0;
4394 *second = 0;
4395 *micro_second = 0;
4396 } else if (unlikely(columnData->length < 0)) {
4397 dbInconsistent("sqlColumnDuration", "SQLBindCol");
4398 logError(printf("sqlColumnDuration: Column " FMT_D ": "
4399 "Negative length: " FMT_D_LEN "\n",
4400 column, columnData->length););
4401 raise_error(DATABASE_ERROR);
4402 } else {
4403 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4404 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4405 switch (columnDescr->dataType) {
4406 case SQL_INTERVAL_YEAR:
4407 case SQL_INTERVAL_MONTH:
4408 case SQL_INTERVAL_DAY:
4409 case SQL_INTERVAL_HOUR:
4410 case SQL_INTERVAL_MINUTE:
4411 case SQL_INTERVAL_SECOND:
4412 case SQL_INTERVAL_YEAR_TO_MONTH:
4413 case SQL_INTERVAL_DAY_TO_HOUR:
4414 case SQL_INTERVAL_DAY_TO_MINUTE:
4415 case SQL_INTERVAL_DAY_TO_SECOND:
4416 case SQL_INTERVAL_HOUR_TO_MINUTE:
4417 case SQL_INTERVAL_HOUR_TO_SECOND:
4418 case SQL_INTERVAL_MINUTE_TO_SECOND:
4419 *year = 0;
4420 *month = 0;
4421 *day = 0;
4422 *hour = 0;
4423 *minute = 0;
4424 *second = 0;
4425 *micro_second = 0;
4426 interval = (SQL_INTERVAL_STRUCT *) columnData->buffer;
4427 /* printf("interval_type: %d\n", interval->interval_type); */
4428 switch (interval->interval_type) {
4429 case SQL_IS_YEAR:
4430 *year = interval->intval.year_month.year;
4431 break;
4432 case SQL_IS_MONTH:
4433 *month = interval->intval.year_month.month;
4434 break;
4435 case SQL_IS_DAY:
4436 *day = interval->intval.day_second.day;
4437 break;
4438 case SQL_IS_HOUR:
4439 *hour = interval->intval.day_second.hour;
4440 break;
4441 case SQL_IS_MINUTE:
4442 *minute = interval->intval.day_second.minute;
4443 break;
4444 case SQL_IS_SECOND:
4445 *second = interval->intval.day_second.second;
4446 break;
4447 case SQL_IS_YEAR_TO_MONTH:
4448 *year = interval->intval.year_month.year;
4449 *month = interval->intval.year_month.month;
4450 break;
4451 case SQL_IS_DAY_TO_HOUR:
4452 *day = interval->intval.day_second.day;
4453 *hour = interval->intval.day_second.hour;
4454 break;
4455 case SQL_IS_DAY_TO_MINUTE:
4456 *day = interval->intval.day_second.day;
4457 *hour = interval->intval.day_second.hour;
4458 *minute = interval->intval.day_second.minute;
4459 break;
4460 case SQL_IS_DAY_TO_SECOND:
4461 *day = interval->intval.day_second.day;
4462 *hour = interval->intval.day_second.hour;
4463 *minute = interval->intval.day_second.minute;
4464 *second = interval->intval.day_second.second;
4465 break;
4466 case SQL_IS_HOUR_TO_MINUTE:
4467 *hour = interval->intval.day_second.hour;
4468 *minute = interval->intval.day_second.minute;
4469 break;
4470 case SQL_IS_HOUR_TO_SECOND:
4471 *hour = interval->intval.day_second.hour;
4472 *minute = interval->intval.day_second.minute;
4473 *second = interval->intval.day_second.second;
4474 break;
4475 case SQL_IS_MINUTE_TO_SECOND:
4476 *minute = interval->intval.day_second.minute;
4477 *second = interval->intval.day_second.second;
4478 break;
4479 } /* switch */
4480 if (interval->interval_sign == SQL_TRUE) {
4481 *year = -*year;
4482 *month = -*month;
4483 *day = -*day;
4484 *hour = -*hour;
4485 *minute = -*minute;
4486 *second = -*second;
4487 *micro_second = -*micro_second;
4488 } /* if */
4489 break;
4490 case SQL_WVARCHAR:
4491 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4492 length = (memSizeType) columnData->length >> 1;
4493 if (unlikely(length > MAX_DURATION_LENGTH)) {
4494 logError(printf("sqlColumnDuration: In column " FMT_D
4495 " the duration length of " FMT_U_MEM " is too long.\n",
4496 column, length););
4497 err_info = RANGE_ERROR;
4498 } else {
4499 err_info = conv_wstri_buf_to_cstri(duration,
4500 (wstriType) columnData->buffer,
4501 length);
4502 if (unlikely(err_info != OKAY_NO_ERROR)) {
4503 logError(printf("sqlColumnDuration: In column " FMT_D
4504 " the duration contains characters byond Latin-1.\n",
4505 column););
4506 } else {
4507 /* printf("sqlColumnDuration: Duration = \"%s\"\n", duration); */
4508 if ((length == 8 && duration[2] == ':' && duration[5] == ':')) {
4509 if (unlikely(sscanf(duration,
4510 F_U(02) ":" F_U(02) ":" F_U(02),
4511 hour, minute, second) != 3)) {
4512 err_info = RANGE_ERROR;
4513 } else {
4514 *year = 0;
4515 *month = 0;
4516 *day = 0;
4517 *micro_second = 0;
4518 } /* if */
4519 } else if (length == 9 && duration[0] == '-' &&
4520 duration[3] == ':' && duration[6] == ':') {
4521 if (unlikely(sscanf(&duration[1],
4522 F_U(02) ":" F_U(02) ":" F_U(02),
4523 hour, minute, second) != 3)) {
4524 err_info = RANGE_ERROR;
4525 } else {
4526 *year = 0;
4527 *month = 0;
4528 *day = 0;
4529 *hour = -*hour;
4530 *minute = -*minute;
4531 *second = -*second;
4532 *micro_second = 0;
4533 } /* if */
4534 } else {
4535 logError(printf("sqlColumnDuration: In column " FMT_D
4536 " the duration \"%s\" is unrecognized.\n",
4537 column, duration););
4538 err_info = RANGE_ERROR;
4539 } /* if */
4540 } /* if */
4541 } /* if */
4542 break;
4543 default:
4544 logError(printf("sqlColumnDuration: Column " FMT_D " has the unknown type %s.\n",
4545 column, nameOfSqlType(columnDescr->dataType)););
4546 err_info = RANGE_ERROR;
4547 break;
4548 } /* switch */
4549 if (unlikely(err_info != OKAY_NO_ERROR)) {
4550 raise_error(err_info);
4551 } /* if */
4552 } /* if */
4553 } /* if */
4554 logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ") --> P"
4555 FMT_D "Y" FMT_D "M" FMT_D "DT"
4556 FMT_D "H" FMT_D "M%s" FMT_U "." F_U(06) "S\n",
4557 (memSizeType) sqlStatement, column,
4558 *year, *month, *day, *hour, *minute,
4559 *second < 0 || *micro_second < 0 ? "-" : "",
4560 intAbs(*second), intAbs(*micro_second)););
4561 } /* sqlColumnDuration */
4562
4563
4564
sqlColumnFloat(sqlStmtType sqlStatement,intType column)4565 static floatType sqlColumnFloat (sqlStmtType sqlStatement, intType column)
4566
4567 {
4568 preparedStmtType preparedStmt;
4569 resultDescrType columnDescr;
4570 resultDataType columnData;
4571 floatType columnValue;
4572
4573 /* sqlColumnFloat */
4574 logFunction(printf("sqlColumnFloat(" FMT_U_MEM ", " FMT_D ")\n",
4575 (memSizeType) sqlStatement, column););
4576 preparedStmt = (preparedStmtType) sqlStatement;
4577 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4578 (uintType) column > preparedStmt->result_array_size)) {
4579 logError(printf("sqlColumnFloat: Fetch okay: %d, column: " FMT_D
4580 ", max column: " FMT_U_MEM ".\n",
4581 preparedStmt->fetchOkay, column,
4582 preparedStmt->result_array_size););
4583 raise_error(RANGE_ERROR);
4584 columnValue = 0.0;
4585 } else {
4586 columnDescr = &preparedStmt->result_descr_array[column - 1];
4587 columnData = &preparedStmt->currentFetch->result_array[column - 1];
4588 if (columnData->length == SQL_NULL_DATA) {
4589 /* printf("Column is NULL -> Use default value: 0.0\n"); */
4590 columnValue = 0.0;
4591 } else if (unlikely(columnData->length < 0)) {
4592 dbInconsistent("sqlColumnFloat", "SQLBindCol");
4593 logError(printf("sqlColumnFloat: Column " FMT_D ": "
4594 "Negative length: " FMT_D_LEN "\n",
4595 column, columnData->length););
4596 raise_error(DATABASE_ERROR);
4597 columnValue = 0.0;
4598 } else if (unlikely(!columnDescr->sql_data_at_exec &&
4599 (SQLULEN) columnData->length > columnDescr->buffer_length)) {
4600 dbInconsistent("sqlColumnFloat", "SQLBindCol");
4601 logError(printf("sqlColumnFloat: Column " FMT_D ": Length (" FMT_D_LEN
4602 ") greater than buffer_length (" FMT_U_MEM ").\n",
4603 column, columnData->length,
4604 columnDescr->buffer_length););
4605 raise_error(DATABASE_ERROR);
4606 columnValue = 0.0;
4607 } else {
4608 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4609 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4610 switch (columnDescr->dataType) {
4611 case SQL_BIT:
4612 columnValue = (floatType) *(char *) columnData->buffer != 0;
4613 break;
4614 case SQL_TINYINT:
4615 /* SQL_TINYINT can be signed or unsigned. */
4616 /* We use a c_type of SQL_C_SSHORT to be on the safe side. */
4617 case SQL_SMALLINT:
4618 columnValue = (floatType) *(int16Type *) columnData->buffer;
4619 break;
4620 case SQL_INTEGER:
4621 columnValue = (floatType) *(int32Type *) columnData->buffer;
4622 break;
4623 case SQL_BIGINT:
4624 columnValue = (floatType) *(int64Type *) columnData->buffer;
4625 break;
4626 case SQL_REAL:
4627 columnValue = *(float *) columnData->buffer;
4628 /* printf("sqlColumnFloat: float: %f\n", columnValue); */
4629 break;
4630 case SQL_FLOAT:
4631 case SQL_DOUBLE:
4632 columnValue = *(double *) columnData->buffer;
4633 /* printf("sqlColumnFloat: double: %f\n", columnValue); */
4634 break;
4635 case SQL_DECIMAL:
4636 columnValue = getDecimalFloat(
4637 (const_ustriType) columnData->buffer,
4638 (memSizeType) columnData->length);
4639 break;
4640 case SQL_NUMERIC:
4641 columnValue = getFloat(
4642 columnData->buffer,
4643 (memSizeType) columnData->length);
4644 break;
4645 default:
4646 logError(printf("sqlColumnFloat: Column " FMT_D " has the unknown type %s.\n",
4647 column, nameOfSqlType(columnDescr->dataType)););
4648 raise_error(RANGE_ERROR);
4649 columnValue = 0.0;
4650 break;
4651 } /* switch */
4652 } /* if */
4653 } /* if */
4654 logFunction(printf("sqlColumnFloat --> " FMT_E "\n", columnValue););
4655 return columnValue;
4656 } /* sqlColumnFloat */
4657
4658
4659
sqlColumnInt(sqlStmtType sqlStatement,intType column)4660 static intType sqlColumnInt (sqlStmtType sqlStatement, intType column)
4661
4662 {
4663 preparedStmtType preparedStmt;
4664 resultDescrType columnDescr;
4665 resultDataType columnData;
4666 intType columnValue;
4667
4668 /* sqlColumnInt */
4669 logFunction(printf("sqlColumnInt(" FMT_U_MEM ", " FMT_D ")\n",
4670 (memSizeType) sqlStatement, column););
4671 preparedStmt = (preparedStmtType) sqlStatement;
4672 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4673 (uintType) column > preparedStmt->result_array_size)) {
4674 logError(printf("sqlColumnInt: Fetch okay: %d, column: " FMT_D
4675 ", max column: " FMT_U_MEM ".\n",
4676 preparedStmt->fetchOkay, column,
4677 preparedStmt->result_array_size););
4678 raise_error(RANGE_ERROR);
4679 columnValue = 0;
4680 } else {
4681 columnDescr = &preparedStmt->result_descr_array[column - 1];
4682 columnData = &preparedStmt->currentFetch->result_array[column - 1];
4683 if (columnData->length == SQL_NULL_DATA) {
4684 /* printf("Column is NULL -> Use default value: 0\n"); */
4685 columnValue = 0;
4686 } else if (unlikely(columnData->length < 0)) {
4687 dbInconsistent("sqlColumnInt", "SQLBindCol");
4688 logError(printf("sqlColumnInt: Column " FMT_D ": "
4689 "Negative length: " FMT_D_LEN "\n",
4690 column, columnData->length););
4691 raise_error(DATABASE_ERROR);
4692 columnValue = 0;
4693 } else {
4694 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4695 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4696 switch (columnDescr->dataType) {
4697 case SQL_BIT:
4698 columnValue = *(char *) columnData->buffer != 0;
4699 break;
4700 case SQL_TINYINT:
4701 /* SQL_TINYINT can be signed or unsigned. */
4702 /* We use a c_type of SQL_C_SSHORT to be on the safe side. */
4703 case SQL_SMALLINT:
4704 columnValue = *(int16Type *) columnData->buffer;
4705 break;
4706 case SQL_INTEGER:
4707 columnValue = *(int32Type *) columnData->buffer;
4708 break;
4709 case SQL_BIGINT:
4710 columnValue = *(int64Type *) columnData->buffer;
4711 break;
4712 case SQL_DECIMAL:
4713 columnValue = getDecimalInt(
4714 (const_ustriType) columnData->buffer,
4715 (memSizeType) columnData->length);
4716 break;
4717 case SQL_NUMERIC:
4718 columnValue = getInt(
4719 columnData->buffer,
4720 (memSizeType) columnData->length);
4721 break;
4722 default:
4723 logError(printf("sqlColumnInt: Column " FMT_D " has the unknown type %s.\n",
4724 column, nameOfSqlType(columnDescr->dataType)););
4725 raise_error(RANGE_ERROR);
4726 columnValue = 0;
4727 break;
4728 } /* switch */
4729 } /* if */
4730 } /* if */
4731 logFunction(printf("sqlColumnInt --> " FMT_D "\n", columnValue););
4732 return columnValue;
4733 } /* sqlColumnInt */
4734
4735
4736
sqlColumnStri(sqlStmtType sqlStatement,intType column)4737 static striType sqlColumnStri (sqlStmtType sqlStatement, intType column)
4738
4739 {
4740 preparedStmtType preparedStmt;
4741 resultDescrType columnDescr;
4742 resultDataType columnData;
4743 memSizeType length;
4744 wstriType wstri;
4745 cstriType cstri;
4746 errInfoType err_info = OKAY_NO_ERROR;
4747 striType columnValue;
4748
4749 /* sqlColumnStri */
4750 logFunction(printf("sqlColumnStri(" FMT_U_MEM ", " FMT_D ")\n",
4751 (memSizeType) sqlStatement, column););
4752 preparedStmt = (preparedStmtType) sqlStatement;
4753 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4754 (uintType) column > preparedStmt->result_array_size)) {
4755 logError(printf("sqlColumnStri: Fetch okay: %d, column: " FMT_D
4756 ", max column: " FMT_U_MEM ".\n",
4757 preparedStmt->fetchOkay, column,
4758 preparedStmt->result_array_size););
4759 raise_error(RANGE_ERROR);
4760 columnValue = NULL;
4761 } else {
4762 columnDescr = &preparedStmt->result_descr_array[column - 1];
4763 columnData = &preparedStmt->currentFetch->result_array[column - 1];
4764 if (columnData->length == SQL_NULL_DATA) {
4765 /* printf("Column is NULL -> Use default value: \"\"\n"); */
4766 columnValue = strEmpty();
4767 } else if (unlikely(columnData->length < 0)) {
4768 dbInconsistent("sqlColumnStri", "SQLBindCol");
4769 logError(printf("sqlColumnStri: Column " FMT_D ": "
4770 "Negative length: " FMT_D_LEN "\n",
4771 column, columnData->length););
4772 raise_error(DATABASE_ERROR);
4773 columnValue = NULL;
4774 } else if (unlikely(!columnDescr->sql_data_at_exec &&
4775 (SQLULEN) columnData->length > columnDescr->buffer_length)) {
4776 dbInconsistent("sqlColumnStri", "SQLBindCol");
4777 logError(printf("sqlColumnStri: Column " FMT_D ": Length (" FMT_D_LEN
4778 ") greater than buffer_length (" FMT_U_MEM ").\n",
4779 column, columnData->length,
4780 columnDescr->buffer_length););
4781 raise_error(DATABASE_ERROR);
4782 columnValue = NULL;
4783 } else {
4784 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4785 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4786 /* printf("c_type: %s\n", nameOfCType(columnDescr->c_type)); */
4787 switch (columnDescr->dataType) {
4788 case SQL_VARCHAR:
4789 case SQL_LONGVARCHAR:
4790 case SQL_WVARCHAR:
4791 case SQL_WLONGVARCHAR:
4792 switch (columnDescr->c_type) {
4793 case SQL_C_CHAR:
4794 columnValue = cstri_buf_to_stri(
4795 (cstriType) columnData->buffer,
4796 (memSizeType) columnData->length);
4797 if (unlikely(columnValue == NULL)) {
4798 raise_error(MEMORY_ERROR);
4799 } /* if */
4800 break;
4801 case SQL_C_WCHAR:
4802 length = (memSizeType) columnData->length >> 1;
4803 columnValue = wstri_buf_to_stri(
4804 (wstriType) columnData->buffer,
4805 length, &err_info);
4806 if (unlikely(columnValue == NULL)) {
4807 raise_error(err_info);
4808 } /* if */
4809 break;
4810 default:
4811 logError(printf("sqlColumnStri: Column " FMT_D " has the unknown C type %s.\n",
4812 column, nameOfCType(columnDescr->c_type)););
4813 raise_error(RANGE_ERROR);
4814 columnValue = NULL;
4815 break;
4816 } /* switch */
4817 break;
4818 case SQL_CHAR:
4819 case SQL_WCHAR:
4820 switch (columnDescr->c_type) {
4821 case SQL_C_CHAR:
4822 length = (memSizeType) columnData->length;
4823 cstri = (cstriType) columnData->buffer;
4824 while (length > 0 && cstri[length - 1] == ' ') {
4825 length--;
4826 } /* if */
4827 columnValue = cstri_buf_to_stri(cstri, length);
4828 if (unlikely(columnValue == NULL)) {
4829 raise_error(MEMORY_ERROR);
4830 } /* if */
4831 break;
4832 case SQL_C_WCHAR:
4833 length = (memSizeType) columnData->length >> 1;
4834 wstri = (wstriType) columnData->buffer;
4835 while (length > 0 && wstri[length - 1] == ' ') {
4836 length--;
4837 } /* if */
4838 columnValue = wstri_buf_to_stri(wstri, length, &err_info);
4839 if (unlikely(columnValue == NULL)) {
4840 raise_error(err_info);
4841 } /* if */
4842 break;
4843 default:
4844 logError(printf("sqlColumnStri: Column " FMT_D " has the unknown C type %s.\n",
4845 column, nameOfCType(columnDescr->c_type)););
4846 raise_error(RANGE_ERROR);
4847 columnValue = NULL;
4848 break;
4849 } /* switch */
4850 break;
4851 case SQL_BINARY:
4852 case SQL_VARBINARY:
4853 case SQL_LONGVARBINARY:
4854 /* This might be a blob, which is filled by fetchBlobs(). */
4855 columnValue = cstri_buf_to_stri(
4856 (cstriType) columnData->buffer,
4857 (memSizeType) columnData->length);
4858 if (unlikely(columnValue == NULL)) {
4859 raise_error(MEMORY_ERROR);
4860 } /* if */
4861 break;
4862 default:
4863 logError(printf("sqlColumnStri: Column " FMT_D " has the unknown type %s.\n",
4864 column, nameOfSqlType(columnDescr->dataType)););
4865 raise_error(RANGE_ERROR);
4866 columnValue = NULL;
4867 break;
4868 } /* switch */
4869 } /* if */
4870 } /* if */
4871 logFunction(printf("sqlColumnStri --> \"%s\"\n", striAsUnquotedCStri(columnValue)););
4872 return columnValue;
4873 } /* sqlColumnStri */
4874
4875
4876
sqlColumnTime(sqlStmtType sqlStatement,intType column,intType * year,intType * month,intType * day,intType * hour,intType * minute,intType * second,intType * micro_second,intType * time_zone,boolType * is_dst)4877 static void sqlColumnTime (sqlStmtType sqlStatement, intType column,
4878 intType *year, intType *month, intType *day, intType *hour,
4879 intType *minute, intType *second, intType *micro_second,
4880 intType *time_zone, boolType *is_dst)
4881
4882 {
4883 preparedStmtType preparedStmt;
4884 resultDescrType columnDescr;
4885 resultDataType columnData;
4886 SQL_DATE_STRUCT *dateValue;
4887 SQL_TIME_STRUCT *timeValue;
4888 SQL_TIMESTAMP_STRUCT *timestampValue;
4889 sqlSsTime2Struct *time2Value;
4890 memSizeType length;
4891 char datetime2[MAX_DATETIME2_LENGTH + NULL_TERMINATION_LEN];
4892 boolType okay;
4893 boolType isTime;
4894 errInfoType err_info = OKAY_NO_ERROR;
4895
4896 /* sqlColumnTime */
4897 logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", *)\n",
4898 (memSizeType) sqlStatement, column););
4899 preparedStmt = (preparedStmtType) sqlStatement;
4900 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4901 (uintType) column > preparedStmt->result_array_size)) {
4902 logError(printf("sqlColumnTime: Fetch okay: %d, column: " FMT_D
4903 ", max column: " FMT_U_MEM ".\n",
4904 preparedStmt->fetchOkay, column,
4905 preparedStmt->result_array_size););
4906 raise_error(RANGE_ERROR);
4907 } else {
4908 columnDescr = &preparedStmt->result_descr_array[column - 1];
4909 columnData = &preparedStmt->currentFetch->result_array[column - 1];
4910 if (columnData->length == SQL_NULL_DATA) {
4911 /* printf("Column is NULL -> Use default value: 0-01-01 00:00:00\n"); */
4912 *year = 0;
4913 *month = 1;
4914 *day = 1;
4915 *hour = 0;
4916 *minute = 0;
4917 *second = 0;
4918 *micro_second = 0;
4919 *time_zone = 0;
4920 *is_dst = 0;
4921 } else if (unlikely(columnData->length < 0)) {
4922 dbInconsistent("sqlColumnTime", "SQLBindCol");
4923 logError(printf("sqlColumnTime: Column " FMT_D ": "
4924 "Negative length: " FMT_D_LEN "\n",
4925 column, columnData->length););
4926 raise_error(DATABASE_ERROR);
4927 } else {
4928 /* printf("length: " FMT_D_LEN "\n", columnData->length); */
4929 /* printf("dataType: %s\n", nameOfSqlType(columnDescr->dataType)); */
4930 switch (columnDescr->dataType) {
4931 case SQL_TYPE_DATE:
4932 dateValue = (SQL_DATE_STRUCT *) columnData->buffer;
4933 *year = dateValue->year;
4934 *month = dateValue->month;
4935 *day = dateValue->day;
4936 *hour = 0;
4937 *minute = 0;
4938 *second = 0;
4939 *micro_second = 0;
4940 timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
4941 time_zone, is_dst);
4942 break;
4943 case SQL_TYPE_TIME:
4944 timeValue = (SQL_TIME_STRUCT *) columnData->buffer;
4945 *year = 2000;
4946 *month = 1;
4947 *day = 1;
4948 *hour = timeValue->hour;
4949 *minute = timeValue->minute;
4950 *second = timeValue->second;
4951 *micro_second = 0;
4952 timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
4953 time_zone, is_dst);
4954 *year = 0;
4955 break;
4956 case SQL_DATETIME:
4957 case SQL_TYPE_TIMESTAMP:
4958 timestampValue = (SQL_TIMESTAMP_STRUCT *) columnData->buffer;
4959 *year = timestampValue->year;
4960 *month = timestampValue->month;
4961 *day = timestampValue->day;
4962 *hour = timestampValue->hour;
4963 *minute = timestampValue->minute;
4964 *second = timestampValue->second;
4965 *micro_second = timestampValue->fraction / 1000;
4966 timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
4967 time_zone, is_dst);
4968 break;
4969 case SQL_SS_TIME2:
4970 time2Value = (sqlSsTime2Struct *) columnData->buffer;
4971 *year = 2000;
4972 *month = 1;
4973 *day = 1;
4974 *hour = time2Value->hour;
4975 *minute = time2Value->minute;
4976 *second = time2Value->second;
4977 *micro_second = time2Value->fraction / 1000;
4978 timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
4979 time_zone, is_dst);
4980 *year = 0;
4981 break;
4982 case SQL_WVARCHAR:
4983 length = (memSizeType) columnData->length >> 1;
4984 if (unlikely(length > MAX_DATETIME2_LENGTH)) {
4985 logError(printf("sqlColumnTime: In column " FMT_D
4986 " the datetime2 length of " FMT_U_MEM " is too long.\n",
4987 column, length););
4988 err_info = RANGE_ERROR;
4989 } else {
4990 err_info = conv_wstri_buf_to_cstri(datetime2,
4991 (wstriType) columnData->buffer, length);
4992 if (unlikely(err_info != OKAY_NO_ERROR)) {
4993 logError(printf("sqlColumnTime: In column " FMT_D
4994 " the datetime2 contains characters byond Latin-1.\n",
4995 column););
4996 } else {
4997 okay = assignTime(datetime2, year, month, day, hour, minute,
4998 second, micro_second, &isTime);
4999 if (unlikely(!okay)) {
5000 logError(printf("sqlColumnTime: Column " FMT_D ": "
5001 "Failed to recognize time: %s\n",
5002 column, datetime2););
5003 err_info = RANGE_ERROR;
5004 } else if (isTime) {
5005 *year = 2000;
5006 timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
5007 time_zone, is_dst);
5008 *year = 0;
5009 } else {
5010 timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
5011 time_zone, is_dst);
5012 } /* if */
5013 } /* if */
5014 } /* if */
5015 break;
5016 default:
5017 logError(printf("sqlColumnTime: Column " FMT_D " has the unknown type %s.\n",
5018 column, nameOfSqlType(columnDescr->dataType)););
5019 err_info = RANGE_ERROR;
5020 break;
5021 } /* switch */
5022 if (unlikely(err_info != OKAY_NO_ERROR)) {
5023 raise_error(err_info);
5024 } /* if */
5025 } /* if */
5026 } /* if */
5027 logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", "
5028 F_D(04) "-" F_D(02) "-" F_D(02) " "
5029 F_D(02) ":" F_D(02) ":" F_D(02) "."
5030 F_D(06) ", " FMT_D ", %d) -->\n",
5031 (memSizeType) sqlStatement, column,
5032 *year, *month, *day, *hour, *minute, *second,
5033 *micro_second, *time_zone, *is_dst););
5034 } /* sqlColumnTime */
5035
5036
5037
sqlCommit(databaseType database)5038 static void sqlCommit (databaseType database)
5039
5040 {
5041 dbType db;
5042
5043 /* sqlCommit */
5044 logFunction(printf("sqlCommit(" FMT_U_MEM ")\n",
5045 (memSizeType) database););
5046 db = (dbType) database;
5047 if (unlikely(db->connection == SQL_NULL_HANDLE)) {
5048 logError(printf("sqlCommit: Database is not open.\n"););
5049 raise_error(RANGE_ERROR);
5050 } else if (unlikely(SQLEndTran(SQL_HANDLE_DBC, db->connection,
5051 SQL_COMMIT) != SQL_SUCCESS)) {
5052 setDbErrorMsg("sqlCommit", "SQLEndTran",
5053 SQL_HANDLE_DBC, db->connection);
5054 logError(printf("sqlCommit: SQLEndTran SQL_COMMIT:\n%s\n",
5055 dbError.message););
5056 raise_error(DATABASE_ERROR);
5057 } /* if */
5058 logFunction(printf("sqlCommit -->\n"););
5059 } /* sqlCommit */
5060
5061
5062
sqlExecute(sqlStmtType sqlStatement)5063 static void sqlExecute (sqlStmtType sqlStatement)
5064
5065 {
5066 preparedStmtType preparedStmt;
5067 SQLRETURN execute_result;
5068 errInfoType err_info = OKAY_NO_ERROR;
5069
5070 /* sqlExecute */
5071 logFunction(printf("sqlExecute(" FMT_U_MEM ")\n",
5072 (memSizeType) sqlStatement););
5073 preparedStmt = (preparedStmtType) sqlStatement;
5074 /* printf("ppStmt: " FMT_U_MEM "\n", (memSizeType) preparedStmt->ppStmt); */
5075 if (unlikely(!allParametersBound(preparedStmt))) {
5076 dbLibError("sqlExecute", "SQLExecute",
5077 "Unbound statement parameter(s).\n");
5078 raise_error(DATABASE_ERROR);
5079 } else {
5080 if (preparedStmt->executeSuccessful) {
5081 if (unlikely(SQLFreeStmt(preparedStmt->ppStmt, SQL_CLOSE) != SQL_SUCCESS)) {
5082 setDbErrorMsg("sqlExecute", "SQLFreeStmt",
5083 SQL_HANDLE_STMT, preparedStmt->ppStmt);
5084 logError(printf("sqlExecute: SQLFreeStmt SQL_CLOSE:\n%s\n",
5085 dbError.message););
5086 err_info = DATABASE_ERROR;
5087 } else {
5088 preparedStmt->executeSuccessful = FALSE;
5089 freePrefetched(preparedStmt);
5090 } /* if */
5091 } /* if */
5092 if (unlikely(err_info != OKAY_NO_ERROR)) {
5093 raise_error(err_info);
5094 } else {
5095 preparedStmt->fetchOkay = FALSE;
5096 execute_result = SQLExecute(preparedStmt->ppStmt);
5097 #ifdef ALLOW_EXECUTE_SUCCESS_WITH_INFO
5098 if (execute_result == SQL_SUCCESS_WITH_INFO) {
5099 execute_result = SQL_SUCCESS;
5100 } /*if */
5101 #endif
5102 if (execute_result == SQL_NO_DATA || execute_result == SQL_SUCCESS) {
5103 if (preparedStmt->db->maxConcurrentActivities != 0) {
5104 /* The number of concurrent activities is limited. That */
5105 /* means: As long as not all data of this statement has */
5106 /* been fetched a second concurrent activity (e.g. */
5107 /* preparing a new statement) may fail. To be on the */
5108 /* safe side we fetch the whole result of this prepared */
5109 /* statement. The fetched results are stored in a */
5110 /* prefetch list and used when sqlFetch() is called. */
5111 if (preparedStmt->result_array_size != 0) {
5112 err_info = prefetchAll(preparedStmt, &preparedStmt->fetchRecord);
5113 } /* if */
5114 if (unlikely(err_info != OKAY_NO_ERROR)) {
5115 preparedStmt->executeSuccessful = FALSE;
5116 raise_error(err_info);
5117 } else {
5118 preparedStmt->executeSuccessful = TRUE;
5119 preparedStmt->fetchFinished = FALSE;
5120 } /* if */
5121 } else {
5122 preparedStmt->executeSuccessful = TRUE;
5123 preparedStmt->fetchFinished = FALSE;
5124 } /* if */
5125 } else {
5126 setDbErrorMsg("sqlExecute", "SQLExecute",
5127 SQL_HANDLE_STMT, preparedStmt->ppStmt);
5128 logError(printf("sqlExecute: SQLExecute execute_result: %d:\n%s\n",
5129 execute_result, dbError.message););
5130 preparedStmt->executeSuccessful = FALSE;
5131 raise_error(DATABASE_ERROR);
5132 } /* if */
5133 } /* if */
5134 } /* if */
5135 logFunction(printf("sqlExecute -->\n"););
5136 } /* sqlExecute */
5137
5138
5139
sqlFetch(sqlStmtType sqlStatement)5140 static boolType sqlFetch (sqlStmtType sqlStatement)
5141
5142 {
5143 preparedStmtType preparedStmt;
5144 SQLRETURN fetch_result;
5145 errInfoType err_info = OKAY_NO_ERROR;
5146
5147 /* sqlFetch */
5148 logFunction(printf("sqlFetch(" FMT_U_MEM ")\n",
5149 (memSizeType) sqlStatement););
5150 preparedStmt = (preparedStmtType) sqlStatement;
5151 if (unlikely(!preparedStmt->executeSuccessful)) {
5152 dbLibError("sqlFetch", "SQLExecute",
5153 "Execute was not successful.\n");
5154 logError(printf("sqlFetch: Execute was not successful.\n"););
5155 preparedStmt->fetchOkay = FALSE;
5156 raise_error(DATABASE_ERROR);
5157 } else if (preparedStmt->result_array_size == 0) {
5158 preparedStmt->fetchOkay = FALSE;
5159 } else if (!preparedStmt->fetchFinished) {
5160 /* printf("ppStmt: " FMT_U_MEM "\n", (memSizeType) preparedStmt->ppStmt); */
5161 err_info = doFetch(preparedStmt, &preparedStmt->fetchRecord);
5162 if (unlikely(err_info != OKAY_NO_ERROR)) {
5163 preparedStmt->fetchOkay = FALSE;
5164 preparedStmt->fetchFinished = TRUE;
5165 raise_error(err_info);
5166 } else {
5167 fetch_result = preparedStmt->currentFetch->fetch_result;
5168 if (fetch_result == SQL_SUCCESS) {
5169 /* printf("fetch success\n"); */
5170 if (likely(err_info == OKAY_NO_ERROR)) {
5171 preparedStmt->fetchOkay = TRUE;
5172 } else {
5173 preparedStmt->fetchOkay = FALSE;
5174 preparedStmt->fetchFinished = TRUE;
5175 raise_error(err_info);
5176 } /* if */
5177 } else if (fetch_result == SQL_NO_DATA) {
5178 preparedStmt->fetchOkay = FALSE;
5179 preparedStmt->fetchFinished = TRUE;
5180 } else {
5181 /* Errors of SQLFetch() have already been handled. */
5182 } /* if */
5183 } /* if */
5184 } /* if */
5185 logFunction(printf("sqlFetch --> %d\n", preparedStmt->fetchOkay););
5186 return preparedStmt->fetchOkay;
5187 } /* sqlFetch */
5188
5189
5190
sqlGetAutoCommit(databaseType database)5191 static boolType sqlGetAutoCommit (databaseType database)
5192
5193 {
5194 dbType db;
5195 SQLUINTEGER autoCommitState;
5196 boolType autoCommit;
5197
5198 /* sqlGetAutoCommit */
5199 logFunction(printf("sqlGetAutoCommit(" FMT_U_MEM ")\n",
5200 (memSizeType) database););
5201 db = (dbType) database;
5202 if (unlikely(db->connection == SQL_NULL_HANDLE)) {
5203 logError(printf("sqlGetAutoCommit: Database is not open.\n"););
5204 raise_error(RANGE_ERROR);
5205 autoCommit = FALSE;
5206 } else if (unlikely(SQLGetConnectAttrW(db->connection,
5207 SQL_ATTR_AUTOCOMMIT, &autoCommitState, 0, NULL) != SQL_SUCCESS)) {
5208 setDbErrorMsg("sqlGetAutoCommit", "SQLGetConnectAttrW",
5209 SQL_HANDLE_DBC, db->connection);
5210 logError(printf("sqlGetAutoCommit: SQLGetConnectAttrW SQL_ATTR_AUTOCOMMIT:\n%s\n",
5211 dbError.message););
5212 raise_error(DATABASE_ERROR);
5213 autoCommit = FALSE;
5214 } else {
5215 autoCommit = autoCommitState == SQL_AUTOCOMMIT_ON;
5216 } /* if */
5217 logFunction(printf("sqlGetAutoCommit --> %d\n", autoCommit););
5218 return autoCommit;
5219 } /* sqlGetAutoCommit */
5220
5221
5222
sqlIsNull(sqlStmtType sqlStatement,intType column)5223 static boolType sqlIsNull (sqlStmtType sqlStatement, intType column)
5224
5225 {
5226 preparedStmtType preparedStmt;
5227 boolType isNull;
5228
5229 /* sqlIsNull */
5230 logFunction(printf("sqlIsNull(" FMT_U_MEM ", " FMT_D ")\n",
5231 (memSizeType) sqlStatement, column););
5232 preparedStmt = (preparedStmtType) sqlStatement;
5233 if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
5234 (uintType) column > preparedStmt->result_array_size)) {
5235 logError(printf("sqlIsNull: Fetch okay: %d, column: " FMT_D
5236 ", max column: " FMT_U_MEM ".\n",
5237 preparedStmt->fetchOkay, column,
5238 preparedStmt->result_array_size););
5239 raise_error(RANGE_ERROR);
5240 isNull = FALSE;
5241 } else {
5242 isNull = preparedStmt->currentFetch->result_array[column - 1].length == SQL_NULL_DATA;
5243 } /* if */
5244 logFunction(printf("sqlIsNull --> %s\n", isNull ? "TRUE" : "FALSE"););
5245 return isNull;
5246 } /* sqlIsNull */
5247
5248
5249
sqlPrepare(databaseType database,const const_striType sqlStatementStri)5250 static sqlStmtType sqlPrepare (databaseType database,
5251 const const_striType sqlStatementStri)
5252
5253 {
5254 dbType db;
5255 striType statementStri;
5256 wstriType query;
5257 memSizeType queryLength;
5258 errInfoType err_info = OKAY_NO_ERROR;
5259 preparedStmtType preparedStmt;
5260
5261 /* sqlPrepare */
5262 logFunction(printf("sqlPrepare(" FMT_U_MEM ", \"%s\")\n",
5263 (memSizeType) database,
5264 striAsUnquotedCStri(sqlStatementStri)););
5265 db = (dbType) database;
5266 if (unlikely(db->connection == SQL_NULL_HANDLE)) {
5267 logError(printf("sqlPrepare: Database is not open.\n"););
5268 err_info = RANGE_ERROR;
5269 preparedStmt = NULL;
5270 } else {
5271 statementStri = processStatementStri(sqlStatementStri, &err_info);
5272 if (statementStri == NULL) {
5273 preparedStmt = NULL;
5274 } else {
5275 query = stri_to_wstri_buf(statementStri, &queryLength, &err_info);
5276 if (unlikely(query == NULL)) {
5277 preparedStmt = NULL;
5278 } else {
5279 if (queryLength > SQLINTEGER_MAX) {
5280 /* It is not possible to cast queryLength to SQLINTEGER. */
5281 logError(printf("sqlPrepare: Statement string too long (length = " FMT_U_MEM ")\n",
5282 queryLength););
5283 err_info = RANGE_ERROR;
5284 preparedStmt = NULL;
5285 } else if (unlikely(!ALLOC_RECORD2(preparedStmt, preparedStmtRecord,
5286 count.prepared_stmt, count.prepared_stmt_bytes))) {
5287 err_info = MEMORY_ERROR;
5288 } else {
5289 memset(preparedStmt, 0, sizeof(preparedStmtRecord));
5290 if (SQLAllocHandle(SQL_HANDLE_STMT,
5291 db->connection,
5292 &preparedStmt->ppStmt) != SQL_SUCCESS) {
5293 setDbErrorMsg("sqlPrepare", "SQLAllocHandle",
5294 SQL_HANDLE_DBC, db->connection);
5295 logError(printf("sqlPrepare: SQLAllocHandle SQL_HANDLE_STMT:\n%s\n",
5296 dbError.message););
5297 FREE_RECORD2(preparedStmt, preparedStmtRecord,
5298 count.prepared_stmt, count.prepared_stmt_bytes);
5299 err_info = DATABASE_ERROR;
5300 preparedStmt = NULL;
5301 } else if (SQLPrepareW(preparedStmt->ppStmt,
5302 (SQLWCHAR *) query,
5303 (SQLINTEGER) queryLength) != SQL_SUCCESS) {
5304 setDbErrorMsg("sqlPrepare", "SQLPrepare",
5305 SQL_HANDLE_STMT, preparedStmt->ppStmt);
5306 logError(printf("sqlPrepare: SQLPrepare:\n%s\n",
5307 dbError.message););
5308 FREE_RECORD2(preparedStmt, preparedStmtRecord,
5309 count.prepared_stmt, count.prepared_stmt_bytes);
5310 err_info = DATABASE_ERROR;
5311 preparedStmt = NULL;
5312 } else {
5313 preparedStmt->usage_count = 1;
5314 preparedStmt->sqlFunc = db->sqlFunc;
5315 preparedStmt->executeSuccessful = FALSE;
5316 preparedStmt->fetchOkay = FALSE;
5317 preparedStmt->fetchFinished = TRUE;
5318 preparedStmt->db = db;
5319 db->usage_count++;
5320 if (likely(err_info == OKAY_NO_ERROR)) {
5321 err_info = setupParameters(preparedStmt);
5322 if (likely(err_info == OKAY_NO_ERROR)) {
5323 err_info = setupResult(preparedStmt);
5324 if (likely(err_info == OKAY_NO_ERROR)) {
5325 err_info = bindResult(preparedStmt, &preparedStmt->fetchRecord);
5326 } /* if */
5327 } /* if */
5328 } /* if */
5329 if (unlikely(err_info != OKAY_NO_ERROR)) {
5330 freePreparedStmt((sqlStmtType) preparedStmt);
5331 preparedStmt = NULL;
5332 } /* if */
5333 } /* if */
5334 } /* if */
5335 free_wstri(query, statementStri);
5336 } /* if */
5337 FREE_STRI(statementStri, sqlStatementStri->size);
5338 } /* if */
5339 } /* if */
5340 if (unlikely(err_info != OKAY_NO_ERROR)) {
5341 raise_error(err_info);
5342 } /* if */
5343 logFunction(printf("sqlPrepare --> " FMT_U_MEM "\n",
5344 (memSizeType) preparedStmt););
5345 return (sqlStmtType) preparedStmt;
5346 } /* sqlPrepare */
5347
5348
5349
sqlRollback(databaseType database)5350 static void sqlRollback (databaseType database)
5351
5352 {
5353 dbType db;
5354
5355 /* sqlRollback */
5356 logFunction(printf("sqlRollback(" FMT_U_MEM ")\n",
5357 (memSizeType) database););
5358 db = (dbType) database;
5359 if (unlikely(db->connection == SQL_NULL_HANDLE)) {
5360 logError(printf("sqlRollback: Database is not open.\n"););
5361 raise_error(RANGE_ERROR);
5362 } else if (unlikely(SQLEndTran(SQL_HANDLE_DBC, db->connection,
5363 SQL_ROLLBACK) != SQL_SUCCESS)) {
5364 setDbErrorMsg("sqlRollback", "SQLEndTran",
5365 SQL_HANDLE_DBC, db->connection);
5366 logError(printf("sqlRollback: SQLEndTran SQL_ROLLBACK:\n%s\n",
5367 dbError.message););
5368 raise_error(DATABASE_ERROR);
5369 } /* if */
5370 logFunction(printf("sqlRollback -->\n"););
5371 } /* sqlRollback */
5372
5373
5374
sqlSetAutoCommit(databaseType database,boolType autoCommit)5375 static void sqlSetAutoCommit (databaseType database, boolType autoCommit)
5376
5377 {
5378 dbType db;
5379 SQLPOINTER autoCommitState;
5380
5381 /* sqlSetAutoCommit */
5382 logFunction(printf("sqlSetAutoCommit(" FMT_U_MEM ", %d)\n",
5383 (memSizeType) database, autoCommit););
5384 db = (dbType) database;
5385 if (unlikely(db->connection == SQL_NULL_HANDLE)) {
5386 logError(printf("sqlSetAutoCommit: Database is not open.\n"););
5387 raise_error(RANGE_ERROR);
5388 } else {
5389 if (autoCommit) {
5390 autoCommitState = (SQLPOINTER) SQL_AUTOCOMMIT_ON;
5391 } else {
5392 autoCommitState = (SQLPOINTER) SQL_AUTOCOMMIT_OFF;
5393 } /* if */
5394 if (unlikely(SQLSetConnectAttrW(db->connection, SQL_ATTR_AUTOCOMMIT,
5395 autoCommitState, 0) != SQL_SUCCESS)) {
5396 setDbErrorMsg("sqlSetAutoCommit", "SQLSetConnectAttrW",
5397 SQL_HANDLE_DBC, db->connection);
5398 logError(printf("sqlSetAutoCommit: SQLSetConnectAttrW SQL_ATTR_AUTOCOMMIT:\n%s\n",
5399 dbError.message););
5400 raise_error(DATABASE_ERROR);
5401 } /* if */
5402 } /* if */
5403 logFunction(printf("sqlSetAutoCommit -->\n"););
5404 } /* sqlSetAutoCommit */
5405
5406
5407
sqlStmtColumnCount(sqlStmtType sqlStatement)5408 static intType sqlStmtColumnCount (sqlStmtType sqlStatement)
5409
5410 {
5411 preparedStmtType preparedStmt;
5412 intType columnCount;
5413
5414 /* sqlStmtColumnCount */
5415 logFunction(printf("sqlStmtColumnCount(" FMT_U_MEM ")\n",
5416 (memSizeType) sqlStatement););
5417 preparedStmt = (preparedStmtType) sqlStatement;
5418 if (unlikely(preparedStmt->result_array_size > INTTYPE_MAX)) {
5419 raise_error(RANGE_ERROR);
5420 columnCount = 0;
5421 } else {
5422 columnCount = (intType) preparedStmt->result_array_size;
5423 } /* if */
5424 logFunction(printf("sqlStmtColumnCount --> " FMT_D "\n", columnCount););
5425 return columnCount;
5426 } /* sqlStmtColumnCount */
5427
5428
5429
sqlStmtColumnName(sqlStmtType sqlStatement,intType column)5430 static striType sqlStmtColumnName (sqlStmtType sqlStatement, intType column)
5431
5432 {
5433 preparedStmtType preparedStmt;
5434 SQLRETURN returnCode;
5435 SQLSMALLINT stringLength;
5436 wcharType wideNameBuffer[CHARS_IN_NAME_BUFFER + NULL_TERMINATION_LEN];
5437 wstriType wideName;
5438 memSizeType wideNameLength;
5439 errInfoType err_info = OKAY_NO_ERROR;
5440 striType name;
5441
5442 /* sqlStmtColumnName */
5443 logFunction(printf("sqlStmtColumnName(" FMT_U_MEM ", " FMT_D ")\n",
5444 (memSizeType) sqlStatement, column););
5445 preparedStmt = (preparedStmtType) sqlStatement;
5446 if (unlikely(column < 1 ||
5447 (uintType) column > preparedStmt->result_array_size)) {
5448 logError(printf("sqlStmtColumnName: column: " FMT_D
5449 ", max column: " FMT_U_MEM ".\n",
5450 column, preparedStmt->result_array_size););
5451 err_info = RANGE_ERROR;
5452 name = NULL;
5453 } else {
5454 returnCode = SQLColAttributeW(preparedStmt->ppStmt,
5455 (SQLUSMALLINT) column,
5456 SQL_DESC_NAME,
5457 wideNameBuffer,
5458 (SQLSMALLINT) SIZ_WSTRI(CHARS_IN_NAME_BUFFER),
5459 &stringLength,
5460 NULL);
5461 if (returnCode != SQL_SUCCESS &&
5462 returnCode != SQL_SUCCESS_WITH_INFO) {
5463 setDbErrorMsg("sqlStmtColumnName", "SQLColAttributeW",
5464 SQL_HANDLE_STMT, preparedStmt->ppStmt);
5465 logError(printf("sqlStmtColumnName: SQLColAttributeW SQL_DESC_NAME "
5466 "returnCode: %d\n%s\n",
5467 returnCode, dbError.message););
5468 err_info = DATABASE_ERROR;
5469 name = NULL;
5470 } else if (unlikely(stringLength < 0 ||
5471 stringLength > SQLSMALLINT_MAX - 2 * NULL_TERMINATION_LEN)) {
5472 dbInconsistent("sqlStmtColumnName", "SQLColAttributeW");
5473 logError(printf("sqlStmtColumnName: "
5474 "String length negative or too big: %hd\n",
5475 stringLength););
5476 err_info = DATABASE_ERROR;
5477 name = NULL;
5478 } else {
5479 wideNameLength = (memSizeType) (stringLength >> 1);
5480 if (returnCode == SQL_SUCCESS) {
5481 name = wstri_buf_to_stri(wideNameBuffer, wideNameLength, &err_info);
5482 } else if (unlikely(!ALLOC_WSTRI(wideName, wideNameLength))) {
5483 err_info = MEMORY_ERROR;
5484 name = NULL;
5485 } else if (SQLColAttributeW(preparedStmt->ppStmt,
5486 (SQLUSMALLINT) column,
5487 SQL_DESC_NAME,
5488 wideName,
5489 (SQLSMALLINT) SIZ_WSTRI(wideNameLength),
5490 NULL,
5491 NULL) != SQL_SUCCESS) {
5492 setDbErrorMsg("sqlStmtColumnName", "SQLColAttributeW",
5493 SQL_HANDLE_STMT, preparedStmt->ppStmt);
5494 logError(printf("sqlStmtColumnName: SQLColAttributeW SQL_DESC_NAME:\n%s\n",
5495 dbError.message););
5496 UNALLOC_WSTRI(wideName, wideNameLength);
5497 err_info = DATABASE_ERROR;
5498 name = NULL;
5499 } else {
5500 name = wstri_buf_to_stri(wideName, wideNameLength, &err_info);
5501 UNALLOC_WSTRI(wideName, wideNameLength);
5502 } /* if */
5503 } /* if */
5504 } /* if */
5505 if (unlikely(err_info != OKAY_NO_ERROR)) {
5506 raise_error(err_info);
5507 } /* if */
5508 logFunction(printf("sqlStmtColumnName --> \"%s\"\n",
5509 striAsUnquotedCStri(name)););
5510 return name;
5511 } /* sqlStmtColumnName */
5512
5513
5514
setupFuncTable(void)5515 static boolType setupFuncTable (void)
5516
5517 { /* setupFuncTable */
5518 if (sqlFunc == NULL) {
5519 if (ALLOC_RECORD(sqlFunc, sqlFuncRecord, count.sql_func)) {
5520 memset(sqlFunc, 0, sizeof(sqlFuncRecord));
5521 sqlFunc->freeDatabase = &freeDatabase;
5522 sqlFunc->freePreparedStmt = &freePreparedStmt;
5523 sqlFunc->sqlBindBigInt = &sqlBindBigInt;
5524 sqlFunc->sqlBindBigRat = &sqlBindBigRat;
5525 sqlFunc->sqlBindBool = &sqlBindBool;
5526 sqlFunc->sqlBindBStri = &sqlBindBStri;
5527 sqlFunc->sqlBindDuration = &sqlBindDuration;
5528 sqlFunc->sqlBindFloat = &sqlBindFloat;
5529 sqlFunc->sqlBindInt = &sqlBindInt;
5530 sqlFunc->sqlBindNull = &sqlBindNull;
5531 sqlFunc->sqlBindStri = &sqlBindStri;
5532 sqlFunc->sqlBindTime = &sqlBindTime;
5533 sqlFunc->sqlClose = &sqlClose;
5534 sqlFunc->sqlColumnBigInt = &sqlColumnBigInt;
5535 sqlFunc->sqlColumnBigRat = &sqlColumnBigRat;
5536 sqlFunc->sqlColumnBool = &sqlColumnBool;
5537 sqlFunc->sqlColumnBStri = &sqlColumnBStri;
5538 sqlFunc->sqlColumnDuration = &sqlColumnDuration;
5539 sqlFunc->sqlColumnFloat = &sqlColumnFloat;
5540 sqlFunc->sqlColumnInt = &sqlColumnInt;
5541 sqlFunc->sqlColumnStri = &sqlColumnStri;
5542 sqlFunc->sqlColumnTime = &sqlColumnTime;
5543 sqlFunc->sqlCommit = &sqlCommit;
5544 sqlFunc->sqlExecute = &sqlExecute;
5545 sqlFunc->sqlFetch = &sqlFetch;
5546 sqlFunc->sqlGetAutoCommit = &sqlGetAutoCommit;
5547 sqlFunc->sqlIsNull = &sqlIsNull;
5548 sqlFunc->sqlPrepare = &sqlPrepare;
5549 sqlFunc->sqlRollback = &sqlRollback;
5550 sqlFunc->sqlSetAutoCommit = &sqlSetAutoCommit;
5551 sqlFunc->sqlStmtColumnCount = &sqlStmtColumnCount;
5552 sqlFunc->sqlStmtColumnName = &sqlStmtColumnName;
5553 } /* if */
5554 } /* if */
5555 return sqlFunc != NULL;
5556 } /* setupFuncTable */
5557
5558
5559
5560 #if LOG_FUNCTIONS_EVERYWHERE || LOG_FUNCTIONS || VERBOSE_EXCEPTIONS_EVERYWHERE || VERBOSE_EXCEPTIONS
printWstri(wstriType wstri)5561 static void printWstri (wstriType wstri)
5562
5563 { /* printWstri */
5564 while (*wstri != '\0') {
5565 if (*wstri <= 255) {
5566 printf("%c", (char) *wstri);
5567 } else {
5568 printf("\\%u;", (unsigned int) *wstri);
5569 } /* if */
5570 wstri++;
5571 } /* while */
5572 } /* printWstri */
5573 #endif
5574
5575
5576
prepareSqlConnection(SQLHENV * sql_environment,SQLHDBC * connection)5577 static errInfoType prepareSqlConnection (SQLHENV *sql_environment,
5578 SQLHDBC *connection)
5579
5580 {
5581 errInfoType err_info = OKAY_NO_ERROR;
5582
5583 /* prepareSqlConnection */
5584 logFunction(printf("prepareSqlConnection\n"););
5585 if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,
5586 sql_environment) != SQL_SUCCESS) {
5587 logError(printf("prepareSqlConnection: SQLAllocHandle failed\n"););
5588 err_info = MEMORY_ERROR;
5589 } else if (SQLSetEnvAttr(*sql_environment,
5590 SQL_ATTR_ODBC_VERSION,
5591 (SQLPOINTER) SQL_OV_ODBC3,
5592 SQL_IS_INTEGER) != SQL_SUCCESS) {
5593 setDbErrorMsg("prepareSqlConnection", "SQLSetEnvAttr",
5594 SQL_HANDLE_ENV, *sql_environment);
5595 logError(printf("prepareSqlConnection: SQLSetEnvAttr "
5596 "SQL_ATTR_ODBC_VERSION:\n%s\n",
5597 dbError.message););
5598 err_info = DATABASE_ERROR;
5599 SQLFreeHandle(SQL_HANDLE_ENV, *sql_environment);
5600 } else if (SQLAllocHandle(SQL_HANDLE_DBC, *sql_environment,
5601 connection) != SQL_SUCCESS) {
5602 setDbErrorMsg("prepareSqlConnection", "SQLAllocHandle",
5603 SQL_HANDLE_ENV, *sql_environment);
5604 logError(printf("prepareSqlConnection: SQLAllocHandle "
5605 "SQL_HANDLE_DBC:\n%s\n", dbError.message););
5606 err_info = DATABASE_ERROR;
5607 SQLFreeHandle(SQL_HANDLE_ENV, *sql_environment);
5608 } /* if */
5609 logFunction(printf("prepareSqlConnection --> %d\n", err_info););
5610 return err_info;
5611 } /* prepareSqlConnection */
5612
5613
5614
createDbRecord(SQLHENV sql_environment,SQLHDBC connection,intType driver,errInfoType * err_info)5615 static databaseType createDbRecord (SQLHENV sql_environment, SQLHDBC connection,
5616 intType driver, errInfoType *err_info)
5617
5618 {
5619 SQLUSMALLINT maxConcurrentActivities;
5620 boolType wideCharsSupported;
5621 boolType tinyintIsUnsigned;
5622 dbType database;
5623
5624 /* createDbRecord */
5625 logFunction(printf("createDbRecord(*, *, " FMT_D ", %d)\n",
5626 driver, *err_info););
5627 if (SQLGetInfoW(connection,
5628 SQL_MAX_CONCURRENT_ACTIVITIES,
5629 (SQLPOINTER) &maxConcurrentActivities,
5630 sizeof(maxConcurrentActivities),
5631 NULL) != SQL_SUCCESS) {
5632 setDbErrorMsg("createDbRecord", "SQLGetInfoW",
5633 SQL_HANDLE_DBC, connection);
5634 logError(printf("createDbRecord: SQLGetInfoW:\n%s\n",
5635 dbError.message););
5636 *err_info = DATABASE_ERROR;
5637 } else {
5638 #ifdef WIDE_CHARS_SUPPORTED
5639 wideCharsSupported = WIDE_CHARS_SUPPORTED;
5640 #else
5641 wideCharsSupported = hasDataType(connection, SQL_WCHAR, err_info);
5642 #endif
5643 #ifdef TINY_INT_IS_UNSIGNED
5644 tinyintIsUnsigned = TINY_INT_IS_UNSIGNED;
5645 #else
5646 tinyintIsUnsigned = dataTypeIsUnsigned(connection, SQL_TINYINT, err_info);
5647 #endif
5648 if (likely(*err_info == OKAY_NO_ERROR)) {
5649 if (unlikely(!setupFuncTable() ||
5650 !ALLOC_RECORD2(database, dbRecord,
5651 count.database, count.database_bytes))) {
5652 *err_info = MEMORY_ERROR;
5653 } /* if */
5654 } /* if */
5655 } /* if */
5656 if (unlikely(*err_info != OKAY_NO_ERROR)) {
5657 SQLDisconnect(connection);
5658 SQLFreeHandle(SQL_HANDLE_DBC, connection);
5659 SQLFreeHandle(SQL_HANDLE_ENV, sql_environment);
5660 database = NULL;
5661 } else {
5662 /* printf("maxConcurrentActivities: %lu\n", (unsigned long) maxConcurrentActivities); */
5663 memset(database, 0, sizeof(dbRecord));
5664 database->usage_count = 1;
5665 database->sqlFunc = sqlFunc;
5666 database->driver = driver;
5667 database->sql_environment = sql_environment;
5668 database->connection = connection;
5669 database->wideCharsSupported = wideCharsSupported;
5670 database->tinyintIsUnsigned = tinyintIsUnsigned;
5671 database->maxConcurrentActivities = maxConcurrentActivities;
5672 } /* if */
5673 logFunction(printf("createDbRecord --> " FMT_U_MEM " (err_info=%d)\n",
5674 (memSizeType) database, *err_info););
5675 return (databaseType) database;
5676 } /* createDbRecord */
5677