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                          &param->dataType,
956                          &param->paramSize,
957                          &param->decimalDigits,
958                          &param->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(&param->buffer,
2884                                              &param->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(&param->buffer, &param->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                                         &param->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                                       &param->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                                         &param->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