1 /********************************************************************/
2 /*                                                                  */
3 /*  sql_tds.c    Database access functions for Tabular Data Stream. */
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_tds.c                                       */
27 /*  Changes: 2017, 2019, 2020  Thomas Mertes                        */
28 /*  Content: Database access functions for Tabular Data Stream.     */
29 /*                                                                  */
30 /********************************************************************/
31 
32 #define LOG_FUNCTIONS 0
33 #define VERBOSE_EXCEPTIONS 0
34 
35 #include "version.h"
36 
37 #include "stdlib.h"
38 #include "stdio.h"
39 #include "string.h"
40 #include "time.h"
41 #ifdef TDS_INCLUDE
42 #if TDS_INCLUDE_SYBFRONT_H
43 #include "sybfront.h"
44 #endif
45 #include TDS_INCLUDE
46 #endif
47 
48 #include "common.h"
49 #include "data_rtl.h"
50 #include "striutl.h"
51 #include "heaputl.h"
52 #include "numutl.h"
53 #include "int_rtl.h"
54 #include "flt_rtl.h"
55 #include "str_rtl.h"
56 #include "tim_rtl.h"
57 #include "bst_rtl.h"
58 #include "big_drv.h"
59 #include "rtl_err.h"
60 #include "dll_drv.h"
61 #include "sql_base.h"
62 #include "sql_drv.h"
63 
64 #ifdef TDS_INCLUDE
65 
66 
67 typedef struct {
68     uintType     usage_count;
69     sqlFuncType  sqlFunc;
70     intType      driver;
71     DBPROCESS   *dbproc;
72     boolType     autoCommit;
73   } dbRecord, *dbType;
74 
75 typedef struct {
76     striType     buffer;
77   } bindDataRecord, *bindDataType;
78 
79 typedef struct {
80     int          buffer_type;
81     memSizeType  buffer_length;
82     void        *buffer;
83   } resultDataRecord, *resultDataType;
84 
85 typedef struct {
86     uintType        usage_count;
87     sqlFuncType     sqlFunc;
88     DBPROCESS      *dbproc;
89     striType       *stmtPartArray;
90     memSizeType     stmtPartArrayCharCount;
91     memSizeType     param_array_size;
92     bindDataType    param_array;
93     memSizeType     result_array_size;
94     resultDataType  result_array;
95     boolType        executeSuccessful;
96     boolType        fetchOkay;
97     boolType        fetchFinished;
98   } preparedStmtRecord, *preparedStmtType;
99 
100 typedef struct {
101     DBPROCESS *dbproc;
102     int severity;
103     int dberr;
104     int oserr;
105     char *dberrstr;
106     char *oserrstr;
107   } errorDescrRecord, *errorDescrType;
108 
109 #define SQL_MAX_NUMERIC_LEN 32
110 typedef struct {
111     unsigned char precision;
112     unsigned char scale;
113     unsigned char sign;
114     unsigned char val[SQL_MAX_NUMERIC_LEN];
115   } numericRecord, *numericType;
116 
117 static sqlFuncType sqlFunc = NULL;
118 static striType quoteQuote = NULL;
119 
120 unsigned int precisionToBytes[] = {0, /* not used */
121                                    1,  1,  2,  2,  3,  3,  3,  4,  4,  5,
122                                    5,  5,  6,  6,  7,  7,  8,  8,  8,  9,
123                                    9, 10, 10, 10, 11, 11, 12, 12, 13, 13,
124                                   13, 14, 14, 15, 15, 15, 16, 16, 17, 17,
125                                   18, 18, 18, 19, 19, 20, 20, 20, 21, 21,
126                                   22, 22, 23, 23, 23, 24, 24, 25, 25, 25,
127                                   26, 26, 27, 27, 27, 28, 28, 29, 29, 30,
128                                   30, 30, 31, 31, 32, 32, 32, 33, 33, 34,
129                                   34, 35, 35, 35, 36, 36, 37, 37, 37, 38,
130                                   38, 39, 39, 40, 40, 40, 41, 41, 42, 42};
131 
132 #define DEFAULT_DECIMAL_SCALE 1000
133 #define INITIAL_ARRAY_SIZE 256
134 #define STMT_TABLE_SIZE_INCREMENT 256
135 #define QUOTE_IN_STRING_LEN 2
136 #define MAX_TIME_LITERAL_LENGTH 34
137 
138 
139 #ifdef TDS_DLL
140 typedef RETCODE (*tp_dbbind) (DBPROCESS *dbproc,
141                               int        column,
142                               int        vartype,
143                               DBINT      varlen,
144                               BYTE      *varaddr);
145 typedef void (*tp_dbclose) (DBPROCESS * dbproc);
146 typedef RETCODE (*tp_dbcmd) (DBPROCESS *dbproc, const char *cmdstring);
147 typedef DBINT (*tp_dbcollen) (DBPROCESS *dbproc, int column);
148 typedef char *(*tp_dbcolname) (DBPROCESS *dbproc, int column);
149 typedef int (*tp_dbcoltype) (DBPROCESS *dbproc, int column);
150 typedef BYTE *(*tp_dbdata) (DBPROCESS *dbproc, int column);
151 typedef DBINT (*tp_dbdatlen) (DBPROCESS *dbproc, int column);
152 typedef EHANDLEFUNC (*tp_dberrhandle) (EHANDLEFUNC handler);
153 typedef void (*tp_dbexit) (void);
154 typedef RETCODE (*tp_dbinit) (void);
155 typedef LOGINREC *(*tp_dblogin) (void);
156 typedef void (*tp_dbloginfree) (LOGINREC *loginptr);
157 typedef MHANDLEFUNC (*tp_dbmsghandle) (MHANDLEFUNC handler);
158 typedef RETCODE (*tp_dbnextrow) (DBPROCESS *dbproc);
159 typedef int (*tp_dbnumcols) (DBPROCESS *dbproc);
160 typedef RETCODE (*tp_dbresults) (DBPROCESS *dbproc);
161 typedef RETCODE (*tp_dbsetlname) (LOGINREC * login, const char *value, int which);
162 typedef RETCODE (*tp_dbsqlexec) (DBPROCESS *dbproc);
163 typedef RETCODE (*tp_dbtablecolinfo) (DBPROCESS *dbproc,
164                                       DBINT      column,
165                                       DBCOL     *pdbcol);
166 typedef RETCODE (*tp_dbuse) (DBPROCESS * dbproc, const char *name);
167 typedef DBPROCESS *(*tp_tdsdbopen) (LOGINREC * login, const char *server, int msdblib);
168 
169 static tp_dbbind         ptr_dbbind;
170 static tp_dbclose        ptr_dbclose;
171 static tp_dbcmd          ptr_dbcmd;
172 static tp_dbcollen       ptr_dbcollen;
173 static tp_dbcolname      ptr_dbcolname;
174 static tp_dbcoltype      ptr_dbcoltype;
175 static tp_dbdata         ptr_dbdata;
176 static tp_dbdatlen       ptr_dbdatlen;
177 static tp_dberrhandle    ptr_dberrhandle;
178 static tp_dbexit         ptr_dbexit;
179 static tp_dbinit         ptr_dbinit;
180 static tp_dblogin        ptr_dblogin;
181 static tp_dbloginfree    ptr_dbloginfree;
182 static tp_dbmsghandle    ptr_dbmsghandle;
183 static tp_dbnextrow      ptr_dbnextrow;
184 static tp_dbnumcols      ptr_dbnumcols;
185 static tp_dbresults      ptr_dbresults;
186 static tp_dbsetlname     ptr_dbsetlname;
187 static tp_dbsqlexec      ptr_dbsqlexec;
188 static tp_dbtablecolinfo ptr_dbtablecolinfo;
189 static tp_dbuse          ptr_dbuse;
190 static tp_tdsdbopen      ptr_tdsdbopen;
191 
192 #define dbbind         ptr_dbbind
193 #define dbclose        ptr_dbclose
194 #define dbcmd          ptr_dbcmd
195 #define dbcollen       ptr_dbcollen
196 #define dbcolname      ptr_dbcolname
197 #define dbcoltype      ptr_dbcoltype
198 #define dbdata         ptr_dbdata
199 #define dbdatlen       ptr_dbdatlen
200 #define dberrhandle    ptr_dberrhandle
201 #define dbexit         ptr_dbexit
202 #define dbinit         ptr_dbinit
203 #define dblogin        ptr_dblogin
204 #define dbloginfree    ptr_dbloginfree
205 #define dbmsghandle    ptr_dbmsghandle
206 #define dbnextrow      ptr_dbnextrow
207 #define dbnumcols      ptr_dbnumcols
208 #define dbresults      ptr_dbresults
209 #define dbsetlname     ptr_dbsetlname
210 #define dbsqlexec      ptr_dbsqlexec
211 #define dbtablecolinfo ptr_dbtablecolinfo
212 #define dbuse          ptr_dbuse
213 #define tdsdbopen      ptr_tdsdbopen
214 
215 
216 
setupDll(const char * dllName)217 static boolType setupDll (const char *dllName)
218 
219   {
220     static void *dbDll = NULL;
221 
222   /* setupDll */
223     logFunction(printf("setupDll(\"%s\")\n", dllName););
224     if (dbDll == NULL) {
225       dbDll = dllOpen(dllName);
226       if (dbDll != NULL) {
227         if ((dbbind         = (tp_dbbind)         dllFunc(dbDll, "dbbind"))         == NULL ||
228             (dbclose        = (tp_dbclose)        dllFunc(dbDll, "dbclose"))        == NULL ||
229             (dbcmd          = (tp_dbcmd)          dllFunc(dbDll, "dbcmd"))          == NULL ||
230             (dbcollen       = (tp_dbcollen)       dllFunc(dbDll, "dbcollen"))       == NULL ||
231             (dbcolname      = (tp_dbcolname)      dllFunc(dbDll, "dbcolname"))      == NULL ||
232             (dbcoltype      = (tp_dbcoltype)      dllFunc(dbDll, "dbcoltype"))      == NULL ||
233             (dbdata         = (tp_dbdata)         dllFunc(dbDll, "dbdata"))         == NULL ||
234             (dbdatlen       = (tp_dbdatlen)       dllFunc(dbDll, "dbdatlen"))       == NULL ||
235             (dberrhandle    = (tp_dberrhandle)    dllFunc(dbDll, "dberrhandle"))    == NULL ||
236             (dbexit         = (tp_dbexit)         dllFunc(dbDll, "dbexit"))         == NULL ||
237             (dbinit         = (tp_dbinit)         dllFunc(dbDll, "dbinit"))         == NULL ||
238             (dblogin        = (tp_dblogin)        dllFunc(dbDll, "dblogin"))        == NULL ||
239             (dbloginfree    = (tp_dbloginfree)    dllFunc(dbDll, "dbloginfree"))    == NULL ||
240             (dbmsghandle    = (tp_dbmsghandle)    dllFunc(dbDll, "dbmsghandle"))    == NULL ||
241             (dbnextrow      = (tp_dbnextrow)      dllFunc(dbDll, "dbnextrow"))      == NULL ||
242             (dbnumcols      = (tp_dbnumcols)      dllFunc(dbDll, "dbnumcols"))      == NULL ||
243             (dbresults      = (tp_dbresults)      dllFunc(dbDll, "dbresults"))      == NULL ||
244             (dbsetlname     = (tp_dbsetlname)     dllFunc(dbDll, "dbsetlname"))     == NULL ||
245             (dbsqlexec      = (tp_dbsqlexec)      dllFunc(dbDll, "dbsqlexec"))      == NULL ||
246             (dbtablecolinfo = (tp_dbtablecolinfo) dllFunc(dbDll, "dbtablecolinfo")) == NULL ||
247             (dbuse          = (tp_dbuse)          dllFunc(dbDll, "dbuse"))          == NULL ||
248             (tdsdbopen      = (tp_tdsdbopen)      dllFunc(dbDll, "tdsdbopen"))      == NULL) {
249           dbDll = NULL;
250         } /* if */
251       } /* if */
252     } /* if */
253     logFunction(printf("setupDll --> %d\n", dbDll != NULL););
254     return dbDll != NULL;
255   } /* setupDll */
256 
257 
258 
findDll(void)259 static boolType findDll (void)
260 
261   {
262     const char *dllList[] = { TDS_DLL };
263     unsigned int pos;
264     boolType found = FALSE;
265 
266   /* findDll */
267     for (pos = 0; pos < sizeof(dllList) / sizeof(char *) && !found; pos++) {
268       found = setupDll(dllList[pos]);
269     } /* for */
270     if (!found) {
271       dllErrorMessage("sqlOpenTds", "findDll", dllList,
272                       sizeof(dllList) / sizeof(char *));
273     } /* if */
274     return found;
275   } /* findDll */
276 
277 #else
278 
279 #define findDll() TRUE
280 
281 #endif
282 
283 
284 
285 static void sqlClose (databaseType database);
286 
287 
288 
err_handler(DBPROCESS * dbproc,int severity,int dberr,int oserr,char * dberrstr,char * oserrstr)289 static int err_handler (DBPROCESS *dbproc, int severity, int dberr,
290     int oserr, char *dberrstr, char *oserrstr)
291 
292   { /* err_handler */
293     logFunction(printf("err_handler(*, %d, %d, %d, %s, %s)\n",
294                        severity, dberr, oserr, dberrstr, oserrstr););
295     snprintf(dbError.message, DB_ERR_MESSAGE_SIZE,
296              "%s\ndberr: %d\n%s\noserr: %d\nseverity: %d\n",
297              dberrstr, dberr, oserrstr, oserr, severity);
298     dbError.errorCode = dberr;
299     if (dberr == SYBETIME) {
300       return INT_TIMEOUT;
301     } else {
302       return INT_CANCEL;
303     } /* if */
304   } /* err_handler */
305 
306 
307 
msg_handler(DBPROCESS * dbproc,DBINT msgno,int msgstate,int severity,char * msgtext,char * srvname,char * procname,int line)308 static int msg_handler (DBPROCESS *dbproc, DBINT msgno, int msgstate,
309     int severity, char *msgtext, char *srvname, char *procname, int line)
310 
311   { /* msg_handler */
312     logFunction(printf("msg_handler(*, %d, %d, %d, %s, %s, %s, %d)\n",
313                        msgno, msgstate, severity, msgtext, srvname, procname, line););
314     return 0;
315   } /* msg_handler */
316 
317 
318 
setDbErrorMsg(const char * funcName,const char * dbFuncName)319 static void setDbErrorMsg (const char *funcName, const char *dbFuncName)
320 
321   { /* setDbErrorMsg */
322     dbError.funcName = funcName;
323     dbError.dbFuncName = dbFuncName;
324   } /* setDbErrorMsg */
325 
326 
327 
doExecute(DBPROCESS * dbproc,const const_cstriType query,errInfoType * err_info)328 static void doExecute (DBPROCESS *dbproc, const const_cstriType query,
329     errInfoType *err_info)
330 
331   {
332     RETCODE retCode;
333 
334   /* doExecute */
335     logFunction(printf("doExecute(*, \"%s\", %d)\n", query, *err_info););
336     if (likely(*err_info == OKAY_NO_ERROR)) {
337       if (unlikely(dbcmd(dbproc, query) != SUCCEED)) {
338         logError(printf("doExecute: dbcmd(" FMT_U_MEM ", \"%s\") failed.\n",
339                         (memSizeType) dbproc, query););
340         *err_info = DATABASE_ERROR;
341       } else if (unlikely(dbsqlexec(dbproc) != SUCCEED)) {
342         logError(printf("doExecute: dbsqlexec(" FMT_U_MEM ") with \"%s\" failed.\n",
343                         (memSizeType) dbproc, query););
344         *err_info = DATABASE_ERROR;
345       } else {
346         retCode = dbresults(dbproc);
347         /* printf("dbresults returns: %d\n", retCode); */
348         if (unlikely(retCode == FAIL)) {
349           logError(printf("doExecute: dbresults() failed.\n"););
350           *err_info = DATABASE_ERROR;
351         } /* if */
352       } /* if */
353     } /* if */
354     logFunction(printf("doExecute --> (err_info=%d)\n", *err_info););
355   } /* doExecute */
356 
357 
358 
359 /**
360  *  Closes a database and frees the memory used by it.
361  */
freeDatabase(databaseType database)362 static void freeDatabase (databaseType database)
363 
364   {
365     dbType db;
366 
367   /* freeDatabase */
368     logFunction(printf("freeDatabase(" FMT_U_MEM ")\n",
369                        (memSizeType) database););
370     sqlClose(database);
371     db = (dbType) database;
372     FREE_RECORD2(db, dbRecord, count.database, count.database_bytes);
373     logFunction(printf("freeDatabase -->\n"););
374   } /* freeDatabase */
375 
376 
377 
freeStmtParts(striType * stmtPartArray,memSizeType partArraySize)378 static void freeStmtParts (striType *stmtPartArray, memSizeType partArraySize)
379 
380   {
381     memSizeType pos;
382 
383   /* freeStmtParts */
384     for (pos = 0; pos < partArraySize; pos++) {
385       FREE_STRI(stmtPartArray[pos], stmtPartArray[pos]->size);
386     } /* for */
387   } /* freeStmtParts */
388 
389 
390 
391 /**
392  *  Closes a prepared statement and frees the memory used by it.
393  */
freePreparedStmt(sqlStmtType sqlStatement)394 static void freePreparedStmt (sqlStmtType sqlStatement)
395 
396   {
397     preparedStmtType preparedStmt;
398     memSizeType pos;
399 
400   /* freePreparedStmt */
401     logFunction(printf("freePreparedStmt(" FMT_U_MEM ")\n",
402                        (memSizeType) sqlStatement););
403     preparedStmt = (preparedStmtType) sqlStatement;
404     freeStmtParts(preparedStmt->stmtPartArray, preparedStmt->param_array_size + 1);
405     if (preparedStmt->param_array != NULL) {
406       for (pos = 0; pos < preparedStmt->param_array_size; pos++) {
407         strDestr(preparedStmt->param_array[pos].buffer);
408       } /* for */
409       FREE_TABLE(preparedStmt->param_array, bindDataRecord, preparedStmt->param_array_size);
410     } /* if */
411     if (preparedStmt->result_array != NULL) {
412       for (pos = 0; pos < preparedStmt->result_array_size; pos++) {
413         if (preparedStmt->result_array[pos].buffer != NULL) {
414           free(preparedStmt->result_array[pos].buffer);
415         } /* if */
416       } /* for */
417       FREE_TABLE(preparedStmt->result_array, resultDataRecord, preparedStmt->result_array_size);
418     } /* if */
419     FREE_RECORD2(preparedStmt, preparedStmtRecord,
420                  count.prepared_stmt, count.prepared_stmt_bytes);
421     logFunction(printf("freePreparedStmt -->\n"););
422   } /* freePreparedStmt */
423 
424 
425 
426 #if LOG_FUNCTIONS_EVERYWHERE || LOG_FUNCTIONS || VERBOSE_EXCEPTIONS_EVERYWHERE || VERBOSE_EXCEPTIONS
nameOfBufferType(int buffer_type)427 static const char *nameOfBufferType (int buffer_type)
428 
429   {
430     static char buffer[50];
431     const char *typeName;
432 
433   /* nameOfBufferType */
434     logFunction(printf("nameOfBufferType(%d)\n", buffer_type););
435     switch (buffer_type) {
436       case SYBVOID:             typeName = "SYBVOID"; break;
437       case SYBIMAGE:            typeName = "SYBIMAGE"; break;
438       case SYBTEXT:             typeName = "SYBTEXT"; break;
439       case SYBVARBINARY:        typeName = "SYBVARBINARY"; break;
440       case SYBINTN:             typeName = "SYBINTN"; break;
441       case SYBVARCHAR:          typeName = "SYBVARCHAR"; break;
442       case SYBMSDATE:           typeName = "SYBMSDATE"; break;
443       case SYBMSTIME:           typeName = "SYBMSTIME"; break;
444       case SYBMSDATETIME2:      typeName = "SYBMSDATETIME2"; break;
445       case SYBMSDATETIMEOFFSET: typeName = "SYBMSDATETIMEOFFSET"; break;
446       case SYBBINARY:           typeName = "SYBBINARY"; break;
447       case SYBCHAR:             typeName = "SYBCHAR"; break;
448       case SYBINT1:             typeName = "SYBINT1"; break;
449       case SYBDATE:             typeName = "SYBDATE"; break;
450       case SYBBIT:              typeName = "SYBBIT"; break;
451       case SYBTIME:             typeName = "SYBTIME"; break;
452       case SYBINT2:             typeName = "SYBINT2"; break;
453       case SYBINT4:             typeName = "SYBINT4"; break;
454       case SYBDATETIME4:        typeName = "SYBDATETIME4"; break;
455       case SYBREAL:             typeName = "SYBREAL"; break;
456       case SYBMONEY:            typeName = "SYBMONEY"; break;
457       case SYBDATETIME:         typeName = "SYBDATETIME"; break;
458       case SYBFLT8:             typeName = "SYBFLT8"; break;
459       case SYBNTEXT:            typeName = "SYBNTEXT"; break;
460       case SYBNVARCHAR:         typeName = "SYBNVARCHAR"; break;
461       case SYBBITN:             typeName = "SYBBITN"; break;
462       case SYBDECIMAL:          typeName = "SYBDECIMAL"; break;
463       case SYBNUMERIC:          typeName = "SYBNUMERIC"; break;
464       case SYBFLTN:             typeName = "SYBFLTN"; break;
465       case SYBMONEYN:           typeName = "SYBMONEYN"; break;
466       case SYBDATETIMN:         typeName = "SYBDATETIMN"; break;
467       case SYBMONEY4:           typeName = "SYBMONEY4"; break;
468       case SYBINT8:             typeName = "SYBINT8"; break;
469       case SYBBIGDATETIME:      typeName = "SYBBIGDATETIME"; break;
470       case SYBBIGTIME:          typeName = "SYBBIGTIME"; break;
471       default:
472         sprintf(buffer, "%d", buffer_type);
473         typeName = buffer;
474         break;
475     } /* switch */
476     logFunction(printf("nameOfBufferType --> %s\n", typeName););
477     return typeName;
478   } /* nameOfBufferType */
479 #endif
480 
481 
482 
storeStmtPart(striType * stmtPartArray,memSizeType partIndex,striType stmtPart,memSizeType stmtPartLength)483 static striType *storeStmtPart (striType *stmtPartArray, memSizeType partIndex,
484     striType stmtPart, memSizeType stmtPartLength)
485 
486   {
487     striType *resizedStmtPartArray;
488     striType copiedStmtPart;
489 
490   /* storeStmtPart */
491     if ((partIndex & (STMT_TABLE_SIZE_INCREMENT - 1)) == 0) {
492       resizedStmtPartArray = REALLOC_TABLE(stmtPartArray, striType, partIndex,
493                                            partIndex + STMT_TABLE_SIZE_INCREMENT);
494       if (unlikely(resizedStmtPartArray == NULL)) {
495         if (stmtPartArray != NULL) {
496           freeStmtParts(stmtPartArray, partIndex);
497           stmtPartArray = NULL;
498         } /* if */
499       } else {
500         stmtPartArray = resizedStmtPartArray;
501         COUNT3_TABLE(striType, partIndex, partIndex + STMT_TABLE_SIZE_INCREMENT);
502       } /* if */
503     } /* if */
504     if (likely(stmtPartArray != NULL)) {
505       if (unlikely(!ALLOC_STRI_SIZE_OK(copiedStmtPart, stmtPartLength))) {
506         freeStmtParts(stmtPartArray, partIndex);
507         stmtPartArray = NULL;
508       } else {
509         copiedStmtPart->size = stmtPartLength;
510         memcpy(copiedStmtPart->mem, stmtPart->mem, stmtPartLength * sizeof(strElemType));
511         /* printf("stmtPart: \"%s\"\n", striAsUnquotedCStri(copiedStmtPart)); */
512         stmtPartArray[partIndex] = copiedStmtPart;
513       } /* if */
514     } /* if */
515     return stmtPartArray;
516   } /* storeStmtPart */
517 
518 
519 
520 /**
521  *  Process the bind variables in a statement string.
522  *  Literals and comments are processed to avoid the misinterpretation
523  *  of question marks (?).
524  */
processStatementStri(const const_striType sqlStatementStri,memSizeType * numBindParameters,errInfoType * err_info)525 static striType *processStatementStri (const const_striType sqlStatementStri,
526     memSizeType *numBindParameters, errInfoType *err_info)
527 
528   {
529     memSizeType pos = 0;
530     strElemType ch;
531     strElemType delimiter;
532     memSizeType destPos = 0;
533     striType processed;
534     memSizeType partIndex = 0;
535     striType *stmtPartArray = NULL;
536 
537   /* processStatementStri */
538     logFunction(printf("processStatementStri(\"%s\", *, *)\n",
539                        striAsUnquotedCStri(sqlStatementStri)););
540     if (unlikely(sqlStatementStri->size > MAX_STRI_LEN ||
541                  !ALLOC_STRI_SIZE_OK(processed, sqlStatementStri->size))) {
542       *err_info = MEMORY_ERROR;
543       *numBindParameters = 0;
544     } else {
545       while (pos < sqlStatementStri->size && *err_info == OKAY_NO_ERROR) {
546         ch = sqlStatementStri->mem[pos];
547         if (ch == '?') {
548           if (destPos == 0 || processed->mem[destPos - 1] != ' ') {
549             /* Make sure that a space precedes the bind parameter. */
550             processed->mem[destPos++] = ' ';
551           } /* if */
552           stmtPartArray = storeStmtPart(stmtPartArray, partIndex, processed, destPos);
553           if (unlikely(stmtPartArray == NULL)) {
554             *err_info = MEMORY_ERROR;
555           } else {
556             partIndex++;
557             destPos = 0;
558             pos++;
559             if (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != ' ') {
560               /* Make sure that a space succeeds the bind parameter. */
561               processed->mem[destPos++] = ' ';
562             } /* if */
563           } /* if */
564         } else if (ch == '\'' || ch == '"') {
565           delimiter = ch;
566           processed->mem[destPos++] = delimiter;
567           pos++;
568           while (pos < sqlStatementStri->size &&
569               (ch = sqlStatementStri->mem[pos]) != delimiter) {
570             processed->mem[destPos++] = ch;
571             pos++;
572           } /* while */
573           if (pos < sqlStatementStri->size) {
574             processed->mem[destPos++] = delimiter;
575             pos++;
576           } /* if */
577         } else if (ch == '/') {
578           pos++;
579           if (pos >= sqlStatementStri->size || sqlStatementStri->mem[pos] != '*') {
580             processed->mem[destPos++] = ch;
581           } else {
582             pos++;
583             do {
584               while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '*') {
585                 pos++;
586               } /* while */
587               pos++;
588             } while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '/');
589             pos++;
590             /* Replace the comment with a space. */
591             processed->mem[destPos++] = ' ';
592           } /* if */
593         } else if (ch == '-') {
594           pos++;
595           if (pos >= sqlStatementStri->size || sqlStatementStri->mem[pos] != '-') {
596             processed->mem[destPos++] = ch;
597           } else {
598             pos++;
599             while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '\n') {
600               pos++;
601             } /* while */
602             /* The final newline replaces the comment. */
603           } /* if */
604         } else {
605           processed->mem[destPos++] = ch;
606           pos++;
607         } /* if */
608       } /* while */
609       if (likely(*err_info == OKAY_NO_ERROR)) {
610         stmtPartArray = storeStmtPart(stmtPartArray, partIndex, processed, destPos);
611         if (unlikely(stmtPartArray == NULL)) {
612           *err_info = MEMORY_ERROR;
613         } /* if */
614       } /* if */
615       FREE_STRI(processed, sqlStatementStri->size);
616       *numBindParameters = partIndex;
617     } /* if */
618     logFunction(printf("processStatementStri(\"%s\", " FMT_U_MEM ", %d) --> ",
619                        striAsUnquotedCStri(sqlStatementStri),
620                        *numBindParameters, *err_info);
621                 if (stmtPartArray == NULL) {
622                   printf("NULL");
623                 } else {
624                   for (partIndex = 0; partIndex <= *numBindParameters; partIndex++) {
625                     printf("\"%s\" ", striAsUnquotedCStri(stmtPartArray[partIndex]));
626                   }
627                 }
628                 printf("\n"););
629     return stmtPartArray;
630   } /* processStatementStri */
631 
632 
633 
getSizeOfBoundStatement(preparedStmtType preparedStmt,errInfoType * err_info)634 static memSizeType getSizeOfBoundStatement (preparedStmtType preparedStmt,
635     errInfoType *err_info)
636 
637   {
638     memSizeType paramIndex;
639     bindDataType bindData;
640     memSizeType sizeOfBoundStatement;
641 
642   /* getSizeOfBoundStatement */
643     sizeOfBoundStatement = preparedStmt->stmtPartArrayCharCount;
644     for (paramIndex = 0; paramIndex < preparedStmt->param_array_size; paramIndex++) {
645       bindData = &preparedStmt->param_array[paramIndex];
646       if (unlikely(bindData->buffer == NULL)) {
647         logError(printf("sqlExecute: Unbound parameter " FMT_U_MEM ".\n",
648                         paramIndex + 1););
649         *err_info = RANGE_ERROR;
650         return 0;
651       } else if (unlikely(sizeOfBoundStatement > MAX_STRI_LEN - bindData->buffer->size)) {
652         *err_info = MEMORY_ERROR;
653         return 0;
654       } else {
655         sizeOfBoundStatement += bindData->buffer->size;
656       } /* if */
657     } /* for */
658     return sizeOfBoundStatement;
659   } /* getSizeOfBoundStatement */
660 
661 
662 
getBoundStatement(preparedStmtType preparedStmt,errInfoType * err_info)663 static striType getBoundStatement (preparedStmtType preparedStmt, errInfoType *err_info)
664 
665   {
666     memSizeType paramIndex;
667     memSizeType pos = 0;
668     memSizeType sizeOfBoundStatement = 0;
669     striType boundStatement;
670 
671   /* getBoundStatement */
672     logFunction(printf("getBoundStatement(*, %d)\n", *err_info););
673     sizeOfBoundStatement = getSizeOfBoundStatement(preparedStmt, err_info);
674     if (unlikely(*err_info != OKAY_NO_ERROR)) {
675       boundStatement = NULL;
676     } else if (unlikely(sizeOfBoundStatement > MAX_STRI_LEN ||
677                         !ALLOC_STRI_SIZE_OK(boundStatement, sizeOfBoundStatement))) {
678       *err_info = MEMORY_ERROR;
679       boundStatement = NULL;
680     } else {
681       boundStatement->size = sizeOfBoundStatement;
682       for (paramIndex = 0; paramIndex < preparedStmt->param_array_size; paramIndex++) {
683         memcpy(&boundStatement->mem[pos], preparedStmt->stmtPartArray[paramIndex]->mem,
684                preparedStmt->stmtPartArray[paramIndex]->size * sizeof(strElemType));
685         pos += preparedStmt->stmtPartArray[paramIndex]->size;
686         memcpy(&boundStatement->mem[pos], preparedStmt->param_array[paramIndex].buffer->mem,
687                preparedStmt->param_array[paramIndex].buffer->size * sizeof(strElemType));
688         pos += preparedStmt->param_array[paramIndex].buffer->size;
689       } /* while */
690       memcpy(&boundStatement->mem[pos], preparedStmt->stmtPartArray[paramIndex]->mem,
691              preparedStmt->stmtPartArray[paramIndex]->size * sizeof(strElemType));
692       /* pos += preparedStmt->stmtPartArray[paramIndex]->size; */
693       /* pos should be equal to boundStatement->size */
694     } /* if */
695     logFunction(printf("getBoundStatement --> \"%s\"\n",
696                        striAsUnquotedCStri(boundStatement)););
697     return boundStatement;
698   } /* getBoundStatement */
699 
700 
701 
setStmtPartArrayCharCount(preparedStmtType preparedStmt,memSizeType numBindParameters)702 static errInfoType setStmtPartArrayCharCount (preparedStmtType preparedStmt,
703     memSizeType numBindParameters)
704 
705   {
706     memSizeType partIndex;
707     memSizeType stmtPartArrayCharCount = 0;
708     errInfoType err_info = OKAY_NO_ERROR;
709 
710   /* setStmtPartArrayCharCount */
711     logFunction(printf("setStmtPartArrayCharCount\n"););
712     for (partIndex = 0; partIndex <= numBindParameters; partIndex++) {
713       if (unlikely(stmtPartArrayCharCount > MAX_STRI_LEN -
714                    preparedStmt->stmtPartArray[partIndex]->size)) {
715         err_info = MEMORY_ERROR;
716         return 0;
717       } else {
718         stmtPartArrayCharCount += preparedStmt->stmtPartArray[partIndex]->size;
719       } /* if */
720     } /* for */
721     preparedStmt->stmtPartArrayCharCount = stmtPartArrayCharCount;
722     logFunction(printf("setStmtPartArrayCharCount --> %d (count=" FMT_U_MEM ")\n",
723                        err_info, stmtPartArrayCharCount););
724     return err_info;
725   } /* setStmtPartArrayCharCount */
726 
727 
728 
setupParameters(preparedStmtType preparedStmt,memSizeType numBindParameters)729 static errInfoType setupParameters (preparedStmtType preparedStmt,
730     memSizeType numBindParameters)
731 
732   {
733     errInfoType err_info = OKAY_NO_ERROR;
734 
735   /* setupParameters */
736     logFunction(printf("setupParameters\n"););
737     if (!ALLOC_TABLE(preparedStmt->param_array,
738                      bindDataRecord, (memSizeType) numBindParameters)) {
739       err_info = MEMORY_ERROR;
740     } else {
741       preparedStmt->param_array_size = (memSizeType) numBindParameters;
742       memset(preparedStmt->param_array, 0,
743              (memSizeType) numBindParameters * sizeof(bindDataRecord));
744     } /* if */
745     logFunction(printf("setupParameters --> %d\n", err_info););
746     return err_info;
747   } /* setupParameters */
748 
749 
750 
setupResultColumn(preparedStmtType preparedStmt,int column_num,resultDataType columnData)751 static errInfoType setupResultColumn (preparedStmtType preparedStmt,
752     int column_num, resultDataType columnData)
753 
754   {
755     DBINT buffer_length;
756     DBCOL dbcol;
757     int bind_type;
758     errInfoType err_info = OKAY_NO_ERROR;
759 
760   /* setupResultColumn */
761     logFunction(printf("setupResultColumn: column_num=%d\n", column_num););
762     dbcol.SizeOfStruct = sizeof(DBCOL);
763     /* The function dbtablecolinfo() distinguishes SYBCHAR from SYBVARCHAR.  */
764     /* The functions dbcoltype() and dbcolinfo() do not distinguish SYBCHAR  */
765     /* from SYBVARCHAR. In sqlColumnStri() trailing spaces of SYBCHAR fields */
766     /* are removed. For SYBVARCHAR fields trailing spaces are preserved.     */
767     if (unlikely(dbtablecolinfo(preparedStmt->dbproc,
768                                 column_num, &dbcol) != SUCCEED)) {
769       setDbErrorMsg("setupResultColumn", "dbtablecolinfo");
770       logError(printf("setupResultColumn: dbtablecolinfo did not succeed:\n%s\n",
771                       dbError.message););
772       err_info = DATABASE_ERROR;
773     } else {
774       /* printf("Type: " FMT_D16 ", VarLength: %d\n", dbcol.Type, dbcol.VarLength); */
775       columnData->buffer_type = dbcol.Type;
776       /* printf("buffer_type: %s\n", nameOfBufferType(columnData->buffer_type)); */
777       switch (columnData->buffer_type) {
778         case SYBCHAR:
779           bind_type = STRINGBIND;
780           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
781           break;
782         case SYBVARCHAR:
783           bind_type = VARYCHARBIND;
784           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
785           break;
786         case SYBINT1:
787           bind_type = TINYBIND;
788           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
789           break;
790         case SYBINT2:
791           bind_type = SMALLBIND;
792           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
793           break;
794         case SYBINT4:
795           bind_type = INTBIND;
796           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
797           break;
798         case SYBINT8:
799           bind_type = INTBIND;
800           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
801           break;
802         case SYBREAL:
803           bind_type = REALBIND;
804           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
805           break;
806         case SYBFLT8:
807           bind_type = FLT8BIND;
808           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
809           break;
810         case SYBDECIMAL:
811           bind_type = DECIMALBIND;
812           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
813           break;
814         case SYBNUMERIC:
815           bind_type = NUMERICBIND;
816           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
817           break;
818         case SYBMSDATE:
819           bind_type = DATEBIND;
820           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
821           break;
822         case SYBMSTIME:
823           bind_type = TIMEBIND;
824           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
825           break;
826         case SYBMSDATETIME2:
827           bind_type = DATETIME2BIND;
828           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
829           break;
830         case SYBBINARY:
831           bind_type = BINARYBIND;
832           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
833           break;
834         case SYBVARBINARY:
835           bind_type = VARYBINBIND;
836           buffer_length = dbcollen(preparedStmt->dbproc, column_num);
837           break;
838         default:
839           logError(printf("setupResultColumn: Column %hd has the unknown type %s.\n",
840                           column_num, nameOfBufferType(columnData->buffer_type)););
841           err_info = RANGE_ERROR;
842           break;
843       } /* switch */
844       if (err_info == OKAY_NO_ERROR) {
845         /* printf("buffer_length[%d]: " FMT_D32 "\n", column_num, buffer_length); */
846         columnData->buffer_length = (memSizeType) buffer_length;
847         /* Binding with dbbind() is not used. The data is retrieved with dbdata() instead. */
848         if (FALSE && buffer_length != 0) {
849           columnData->buffer = malloc((memSizeType) buffer_length);
850           if (unlikely(columnData->buffer == NULL)) {
851             err_info = MEMORY_ERROR;
852           } else {
853             memset(columnData->buffer, 0, (memSizeType) buffer_length);
854             if (unlikely(dbbind(preparedStmt->dbproc, column_num, bind_type,
855                                 buffer_length, (BYTE *) columnData->buffer) != SUCCEED)) {
856               setDbErrorMsg("setupResultColumn", "dbbind");
857               logError(printf("setupResultColumn: dbbind did not succeed:\n%s\n",
858                               dbError.message););
859               err_info = DATABASE_ERROR;
860             } /* if */
861           } /* if */
862         } /* if */
863       } /* if */
864     } /* if */
865     logFunction(printf("setupResultColumn --> %d\n", err_info););
866     return err_info;
867   } /* setupResultColumn */
868 
869 
870 
setupResult(preparedStmtType preparedStmt)871 static errInfoType setupResult (preparedStmtType preparedStmt)
872 
873   {
874     int num_columns;
875     int column_index;
876     errInfoType err_info = OKAY_NO_ERROR;
877 
878   /* setupResult */
879     logFunction(printf("setupResult\n"););
880     num_columns = dbnumcols(preparedStmt->dbproc);
881     /* printf("num_columns: %d\n", num_columns); */
882     if (unlikely(num_columns < 0)) {
883       dbInconsistent("setupResult", "dbnumcols");
884       logError(printf("setupResult: dbnumcols returns negative number: %d\n",
885                       num_columns););
886       err_info = DATABASE_ERROR;
887     } else if (num_columns == 0) {
888       /* malloc(0) may return NULL, which would wrongly trigger a MEMORY_ERROR. */
889       preparedStmt->result_array_size = 0;
890       preparedStmt->result_array = NULL;
891     } else if (unlikely(!ALLOC_TABLE(preparedStmt->result_array,
892                                      resultDataRecord, (memSizeType) num_columns))) {
893       err_info = MEMORY_ERROR;
894     } else {
895       preparedStmt->result_array_size = (memSizeType) num_columns;
896       memset(preparedStmt->result_array, 0,
897           (memSizeType) num_columns * sizeof(resultDataRecord));
898       for (column_index = 0; column_index < num_columns &&
899            err_info == OKAY_NO_ERROR; column_index++) {
900         err_info = setupResultColumn(preparedStmt, column_index + 1,
901                                      &preparedStmt->result_array[column_index]);
902       } /* for */
903     } /* if */
904     logFunction(printf("setupResult --> %d\n", err_info););
905     return err_info;
906   } /* setupResult */
907 
908 
909 
getNumericAsCStri(numericType numStruct)910 static cstriType getNumericAsCStri (numericType numStruct)
911 
912   {
913     memSizeType numBytes;
914     bigIntType mantissa;
915     striType stri;
916     memSizeType decimalLen;
917     memSizeType decimalIdx = 0;
918     memSizeType idx;
919     cstriType decimal;
920 
921   /* getNumericAsCStri */
922     if (unlikely(numStruct->precision == 0 || numStruct->precision > 100)) {
923       raise_error(RANGE_ERROR);
924       decimal = 0;
925     } else {
926       numBytes = (memSizeType) precisionToBytes[numStruct->precision];
927       mantissa = bigFromByteBufferBe(numBytes, numStruct->val, FALSE);
928       if (unlikely(mantissa == NULL)) {
929         decimal = NULL;
930       } else {
931         stri = bigStr(mantissa);
932         if (unlikely(stri == NULL)) {
933           bigDestr(mantissa);
934           raise_error(MEMORY_ERROR);
935           decimal = NULL;
936         } else {
937           if (numStruct->scale < 0) {
938             decimalLen = stri->size + (memSizeType) (-numStruct->scale) + 1 /* Space for decimal point */;
939           } else if (numStruct->scale <= stri->size) {
940             decimalLen = stri->size + 1 /* Space for decimal point */;
941           } else {
942             decimalLen = (memSizeType) numStruct->scale + 1 /* Space for decimal point */;
943           } /* if */
944           if (numStruct->sign != 0) {
945             decimalLen++; /* Space for sign */
946           } /* if */
947           if (unlikely(!ALLOC_CSTRI(decimal, decimalLen))) {
948             bigDestr(mantissa);
949             strDestr(stri);
950             raise_error(MEMORY_ERROR);
951           } else {
952             if (numStruct->sign != 0) {
953               decimal[decimalIdx++] = '-';
954             } /* if */
955             for (idx = 0; idx < stri->size; idx++) {
956               decimal[decimalIdx++] = (char) stri->mem[idx];
957             } /* for */
958             /* decimal[decimalIdx] = '\0';
959             printf("# \"%s\", scale: %d, size: " FMT_U_MEM ", len: " FMT_U_MEM "\n",
960                 decimal, numStruct->scale, stri->size, decimalLen); */
961             if (numStruct->scale < 0) {
962               memset(&decimal[decimalIdx], '0', (memSizeType) (-numStruct->scale));
963               decimal[decimalLen - 1] = '.';
964               decimal[decimalLen] = '\0';
965             } else if (numStruct->scale <= stri->size) {
966               memmove(&decimal[decimalLen - (memSizeType) numStruct->scale],
967                       &decimal[decimalLen - (memSizeType) numStruct->scale - 1],
968                       (memSizeType) numStruct->scale);
969               decimal[decimalLen - (memSizeType) numStruct->scale - 1] = '.';
970               decimal[decimalLen] = '\0';
971             } else {
972               memmove(&decimal[decimalLen - stri->size],
973                       &decimal[decimalLen - (memSizeType) numStruct->scale - 1],
974                       stri->size);
975               memset(&decimal[decimalLen - (memSizeType) numStruct->scale], '0',
976                      (memSizeType) numStruct->scale - stri->size);
977               decimal[decimalLen - (memSizeType) numStruct->scale - 1] = '.';
978               decimal[decimalLen] = '\0';
979             } /* if */
980             bigDestr(mantissa);
981             strDestr(stri);
982           } /* if */
983         } /* if */
984       } /* if */
985     } /* if */
986     logFunction(printf("getNumericAsCStri --> %s\n",
987                        decimal != NULL ? decimal : "NULL"));
988     return decimal;
989   } /* getNumericAsCStri */
990 
991 
992 
getNumericInt(const void * buffer)993 static intType getNumericInt (const void *buffer)
994 
995   {
996     numericType numStruct;
997     memSizeType numBytes;
998     bigIntType bigIntValue;
999     bigIntType powerOfTen;
1000     intType intValue = 0;
1001 
1002   /* getNumericInt */
1003     numStruct = (numericType) buffer;
1004     logFunction(printf("getNumericInt\n");
1005                 printf("numStruct->precision: %u\n", numStruct->precision);
1006                 printf("numStruct->scale: %d\n", numStruct->scale);
1007                 printf("numStruct->sign: %u\n", numStruct->sign);
1008                 printf("numStruct->val:");
1009                 {
1010                   int pos;
1011                   for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
1012                     printf(" %d", numStruct->val[pos]);
1013                   }
1014                   printf("\n");
1015                 });
1016     if (unlikely(numStruct->scale > 0 ||
1017                  numStruct->precision == 0 || numStruct->precision > 100)) {
1018       raise_error(RANGE_ERROR);
1019       intValue = 0;
1020     } else {
1021       numBytes = (memSizeType) precisionToBytes[numStruct->precision];
1022       bigIntValue = bigFromByteBufferBe(numBytes, numStruct->val, FALSE);
1023 #if 0
1024       if (bigIntValue != NULL) {
1025         printf("numStruct->val: ");
1026         prot_bigint(bigIntValue);
1027         printf("\n");
1028       }
1029 #endif
1030       if (bigIntValue != NULL && numStruct->scale < 0) {
1031         powerOfTen = bigIPowSignedDigit(10, (intType) -numStruct->scale);
1032         if (powerOfTen != NULL) {
1033           bigMultAssign(&bigIntValue, powerOfTen);
1034           bigDestr(powerOfTen);
1035         } /* if */
1036       } /* if */
1037       if (bigIntValue != NULL && numStruct->sign != 0) {
1038         bigIntValue = bigNegateTemp(bigIntValue);
1039       } /* if */
1040       if (bigIntValue != NULL) {
1041 #if 0
1042         printf("numStruct->val: ");
1043         prot_bigint(bigIntValue);
1044         printf("\n");
1045 #endif
1046 #if INTTYPE_SIZE == 32
1047         intValue = bigToInt32(bigIntValue, NULL);
1048 #elif INTTYPE_SIZE == 64
1049         intValue = bigToInt64(bigIntValue, NULL);
1050 #endif
1051         bigDestr(bigIntValue);
1052       } /* if */
1053     } /* if */
1054     logFunction(printf("getNumericInt --> " FMT_D "\n", intValue););
1055     return intValue;
1056   } /* getNumericInt */
1057 
1058 
1059 
getNumericBigInt(const void * buffer)1060 static bigIntType getNumericBigInt (const void *buffer)
1061 
1062   {
1063     numericType numStruct;
1064     memSizeType numBytes;
1065     bigIntType powerOfTen;
1066     bigIntType bigIntValue;
1067 
1068   /* getNumericBigInt */
1069     numStruct = (numericType) buffer;
1070     logFunction(printf("getNumericBigInt\n");
1071                 printf("numStruct->precision: %u\n", numStruct->precision);
1072                 printf("numStruct->scale: %d\n", numStruct->scale);
1073                 printf("numStruct->sign: %u\n", numStruct->sign);
1074                 printf("numStruct->val:");
1075                 {
1076                   int pos;
1077                   for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
1078                     printf(" %d", numStruct->val[pos]);
1079                   }
1080                   printf("\n");
1081                 });
1082     if (unlikely(numStruct->scale > 0 ||
1083                  numStruct->precision == 0 || numStruct->precision > 100)) {
1084       raise_error(RANGE_ERROR);
1085       bigIntValue = NULL;
1086     } else {
1087       numBytes = (memSizeType) precisionToBytes[numStruct->precision];
1088       bigIntValue = bigFromByteBufferBe(numBytes, numStruct->val, FALSE);
1089 #if 0
1090       if (bigIntValue != NULL) {
1091         printf("numStruct->val: ");
1092         prot_bigint(bigIntValue);
1093         printf("\n");
1094       } /* if */
1095 #endif
1096       if (bigIntValue != NULL && numStruct->scale < 0) {
1097         powerOfTen = bigIPowSignedDigit(10, (intType) -numStruct->scale);
1098         if (powerOfTen != NULL) {
1099           bigMultAssign(&bigIntValue, powerOfTen);
1100           bigDestr(powerOfTen);
1101         } /* if */
1102       } /* if */
1103       if (bigIntValue != NULL && numStruct->sign != 0) {
1104         bigIntValue = bigNegateTemp(bigIntValue);
1105       } /* if */
1106     } /* if */
1107     logFunction(printf("getNumericBigInt --> ");
1108                 prot_bigint(bigIntValue);
1109                 printf("\n"););
1110     return bigIntValue;
1111  } /* getNumericBigInt */
1112 
1113 
1114 
getNumericBigRational(const void * buffer,bigIntType * denominator)1115 static bigIntType getNumericBigRational (const void *buffer, bigIntType *denominator)
1116 
1117   {
1118     numericType numStruct;
1119     memSizeType numBytes;
1120     bigIntType powerOfTen;
1121     bigIntType numerator;
1122 
1123   /* getNumericBigRational */
1124     numStruct = (numericType) buffer;
1125     logFunction(printf("getNumericBigRational\n");
1126                 printf("numStruct->precision: %u\n", numStruct->precision);
1127                 printf("numStruct->scale: %d\n", numStruct->scale);
1128                 printf("numStruct->sign: %u\n", numStruct->sign);
1129                 printf("numStruct->val:");
1130                 {
1131                   int pos;
1132                   for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
1133                     printf(" %d", numStruct->val[pos]);
1134                   }
1135                   printf("\n");
1136                 });
1137     if (unlikely(numStruct->precision == 0 || numStruct->precision > 100)) {
1138       raise_error(RANGE_ERROR);
1139       numerator = NULL;
1140     } else {
1141       numBytes = (memSizeType) precisionToBytes[numStruct->precision];
1142       numerator = bigFromByteBufferBe(numBytes, numStruct->val, FALSE);
1143 #if 0
1144       if (numerator != NULL) {
1145         printf("numStruct->val: ");
1146         prot_bigint(numerator);
1147         printf("\n");
1148       } /* if */
1149 #endif
1150       if (numerator != NULL && numStruct->sign != 0) {
1151         numerator = bigNegateTemp(numerator);
1152       } /* if */
1153       if (numerator != NULL) {
1154         if (numStruct->scale < 0) {
1155           powerOfTen = bigIPowSignedDigit(10, (intType) -numStruct->scale);
1156           if (powerOfTen != NULL) {
1157             bigMultAssign(&numerator, powerOfTen);
1158             bigDestr(powerOfTen);
1159           } /* if */
1160           *denominator = bigFromInt32(1);
1161         } else {
1162           *denominator = bigIPowSignedDigit(10, (intType) numStruct->scale);
1163         } /* if */
1164       } /* if */
1165     } /* if */
1166     return numerator;
1167   } /* getNumericBigRational */
1168 
1169 
1170 
getNumericFloat(const void * buffer)1171 static floatType getNumericFloat (const void *buffer)
1172 
1173   {
1174     numericType numStruct;
1175     cstriType decimal;
1176     floatType floatValue;
1177 
1178   /* getNumericFloat */
1179     numStruct = (numericType) buffer;
1180     logFunction(printf("getNumericFloat\n");
1181                 printf("numStruct->precision: %u\n", numStruct->precision);
1182                 printf("numStruct->scale: %d\n", numStruct->scale);
1183                 printf("numStruct->sign: %u\n", numStruct->sign);
1184                 printf("numStruct->val:");
1185                 {
1186                   int pos;
1187                   for (pos = 0; pos < SQL_MAX_NUMERIC_LEN; pos++) {
1188                     printf(" %d", numStruct->val[pos]);
1189                   }
1190                   printf("\n");
1191                 });
1192     if (unlikely((decimal = getNumericAsCStri(numStruct)) == NULL)) {
1193       floatValue = 0.0;
1194     } else {
1195       floatValue = (floatType) strtod(decimal, NULL);
1196       UNALLOC_CSTRI(decimal, strlen(decimal));
1197     } /* if */
1198     logFunction(printf("getNumericFloat --> " FMT_E "\n", floatValue););
1199     return floatValue;
1200   } /* getNumericFloat */
1201 
1202 
1203 
genSqlStringLiteral(const const_striType stri)1204 static striType genSqlStringLiteral (const const_striType stri)
1205 
1206   {
1207     /* A string literal starts and ends with double quotes ("): */
1208     const memSizeType numOfQuotes = 2;
1209     register strElemType character;
1210     register memSizeType position;
1211     memSizeType striSize;
1212     memSizeType pos;
1213     striType resized_literal;
1214     striType literal;
1215 
1216   /* genSqlStringLiteral */
1217     striSize = stri->size;
1218     if (unlikely(striSize > (MAX_STRI_LEN - numOfQuotes) / QUOTE_IN_STRING_LEN ||
1219                  !ALLOC_STRI_SIZE_OK(literal, QUOTE_IN_STRING_LEN * striSize + numOfQuotes))) {
1220       raise_error(MEMORY_ERROR);
1221       literal = NULL;
1222     } else {
1223       literal->mem[0] = (strElemType) '\'';
1224       pos = 1;
1225       for (position = 0; position < striSize; position++) {
1226         character = (strElemType) stri->mem[position];
1227         if (character == '\'') {
1228           literal->mem[pos]     = (strElemType) '\'';
1229           literal->mem[pos + 1] = (strElemType) '\'';
1230           pos += 2;
1231         } else {
1232           literal->mem[pos] = character;
1233           pos++;
1234         } /* if */
1235       } /* for */
1236       literal->mem[pos] = (strElemType) '\'';
1237       pos++;
1238       literal->size = pos;
1239       REALLOC_STRI_SIZE_SMALLER(resized_literal, literal,
1240           QUOTE_IN_STRING_LEN * striSize + numOfQuotes, pos);
1241       if (unlikely(resized_literal == NULL)) {
1242         FREE_STRI(literal, QUOTE_IN_STRING_LEN * striSize + numOfQuotes);
1243         raise_error(MEMORY_ERROR);
1244         literal = NULL;
1245       } else {
1246         literal = resized_literal;
1247         COUNT3_STRI(QUOTE_IN_STRING_LEN * striSize + numOfQuotes, pos);
1248       } /* if */
1249     } /* if */
1250     return literal;
1251   } /* genSqlStringLiteral */
1252 
1253 
1254 
sqlBindBigInt(sqlStmtType sqlStatement,intType pos,const const_bigIntType value)1255 static void sqlBindBigInt (sqlStmtType sqlStatement, intType pos,
1256     const const_bigIntType value)
1257 
1258   {
1259     preparedStmtType preparedStmt;
1260 
1261   /* sqlBindBigInt */
1262     logFunction(printf("sqlBindBigInt(" FMT_U_MEM ", " FMT_D ", %s)\n",
1263                        (memSizeType) sqlStatement, pos, bigHexCStri(value)););
1264     preparedStmt = (preparedStmtType) sqlStatement;
1265     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1266       logError(printf("sqlBindBigInt: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1267                       pos, preparedStmt->param_array_size););
1268       raise_error(RANGE_ERROR);
1269     } else {
1270       strDestr(preparedStmt->param_array[pos - 1].buffer);
1271       preparedStmt->param_array[pos - 1].buffer = bigStr(value);
1272     } /* if */
1273   } /* sqlBindBigInt */
1274 
1275 
1276 
sqlBindBigRat(sqlStmtType sqlStatement,intType pos,const const_bigIntType numerator,const const_bigIntType denominator)1277 static void sqlBindBigRat (sqlStmtType sqlStatement, intType pos,
1278     const const_bigIntType numerator, const const_bigIntType denominator)
1279 
1280   {
1281     preparedStmtType preparedStmt;
1282     ustriType decimal;
1283     memSizeType length;
1284     errInfoType err_info = OKAY_NO_ERROR;
1285 
1286   /* sqlBindBigRat */
1287     logFunction(printf("sqlBindBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s)\n",
1288                        (memSizeType) sqlStatement, pos,
1289                        bigHexCStri(numerator), bigHexCStri(denominator)););
1290     preparedStmt = (preparedStmtType) sqlStatement;
1291     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1292       logError(printf("sqlBindBigRat: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1293                       pos, preparedStmt->param_array_size););
1294       raise_error(RANGE_ERROR);
1295     } else {
1296       if (bigEqSignedDigit(denominator, 1)) {
1297         decimal = bigIntToDecimal(numerator, &length, &err_info);
1298       } else {
1299         decimal = bigRatToDecimal(numerator, denominator, DEFAULT_DECIMAL_SCALE,
1300                                   &length, &err_info);
1301       } /* if */
1302       if (unlikely(decimal == NULL)) {
1303         raise_error(err_info);
1304       } else {
1305         strDestr(preparedStmt->param_array[pos - 1].buffer);
1306         preparedStmt->param_array[pos - 1].buffer =
1307             cstri_buf_to_stri((cstriType) decimal, length);
1308         free(decimal);
1309         if (unlikely(preparedStmt->param_array[pos - 1].buffer == NULL)) {
1310           raise_error(MEMORY_ERROR);
1311         } /* if */
1312       } /* if */
1313     } /* if */
1314   } /* sqlBindBigRat */
1315 
1316 
1317 
sqlBindBool(sqlStmtType sqlStatement,intType pos,boolType value)1318 static void sqlBindBool (sqlStmtType sqlStatement, intType pos, boolType value)
1319 
1320   {
1321     preparedStmtType preparedStmt;
1322 
1323   /* sqlBindBool */
1324     logFunction(printf("sqlBindBool(" FMT_U_MEM ", " FMT_D ", %s)\n",
1325                        (memSizeType) sqlStatement, pos, value ? "TRUE" : "FALSE"););
1326     preparedStmt = (preparedStmtType) sqlStatement;
1327     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1328       logError(printf("sqlBindBool: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1329                       pos, preparedStmt->param_array_size););
1330       raise_error(RANGE_ERROR);
1331     } else {
1332       strDestr(preparedStmt->param_array[pos - 1].buffer);
1333       preparedStmt->param_array[pos - 1].buffer = intStr(value);
1334     } /* if */
1335   } /* sqlBindBool */
1336 
1337 
1338 
sqlBindBStri(sqlStmtType sqlStatement,intType pos,const const_bstriType bstri)1339 static void sqlBindBStri (sqlStmtType sqlStatement, intType pos,
1340     const const_bstriType bstri)
1341 
1342   {
1343     const unsigned char digit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
1344                                    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1345     preparedStmtType preparedStmt;
1346     striType stri;
1347     memSizeType idx;
1348 
1349   /* sqlBindBStri */
1350     logFunction(printf("sqlBindBStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
1351                        (memSizeType) sqlStatement, pos, bstriAsUnquotedCStri(bstri)););
1352     preparedStmt = (preparedStmtType) sqlStatement;
1353     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1354       logError(printf("sqlBindBStri: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1355                       pos, preparedStmt->param_array_size););
1356       raise_error(RANGE_ERROR);
1357     } else {
1358       strDestr(preparedStmt->param_array[pos - 1].buffer);
1359       if (unlikely(bstri->size > (MAX_STRI_LEN - 2) / 2 ||
1360                    !ALLOC_STRI_CHECK_SIZE(stri, 2 + 2 * bstri->size))) {
1361         raise_error(MEMORY_ERROR);
1362       } else {
1363         stri->size = 2 + 2 * bstri->size;
1364         stri->mem[0] = '0';
1365         stri->mem[1] = 'x';
1366         for (idx = 0; idx < bstri->size; idx++) {
1367           stri->mem[(idx << 1) + 2] = digit[bstri->mem[idx] >> 4];
1368           stri->mem[(idx << 1) + 3] = digit[bstri->mem[idx] & 0xf];
1369         } /* for */
1370         preparedStmt->param_array[pos - 1].buffer = stri;
1371       } /* if */
1372     } /* if */
1373   } /* sqlBindBStri */
1374 
1375 
1376 
sqlBindDuration(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second)1377 static void sqlBindDuration (sqlStmtType sqlStatement, intType pos,
1378     intType year, intType month, intType day, intType hour,
1379     intType minute, intType second, intType micro_second)
1380 
1381   {
1382     preparedStmtType preparedStmt;
1383 
1384   /* sqlBindDuration */
1385     logFunction(printf("sqlBindDuration(" FMT_U_MEM ", " FMT_D ", P"
1386                                           FMT_D "Y" FMT_D "M" FMT_D "DT"
1387                                           FMT_D "H" FMT_D "M%s%lu.%06luS)\n",
1388                        (memSizeType) sqlStatement, pos,
1389                        year, month, day, hour, minute,
1390                        second < 0 || micro_second < 0 ? "-" : "",
1391                        intAbs(second), intAbs(micro_second)););
1392     preparedStmt = (preparedStmtType) sqlStatement;
1393     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1394       logError(printf("sqlBindDuration: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1395                       pos, preparedStmt->param_array_size););
1396       raise_error(RANGE_ERROR);
1397     } else if (unlikely(year < -9999 || year > 9999 || month < -12 || month > 12 ||
1398                         day < -31 || day > 31 || hour <= -24 || hour >= 24 ||
1399                         minute <= -60 || minute >= 60 || second <= -60 || second >= 60 ||
1400                         micro_second <= -1000000 || micro_second >= 1000000)) {
1401       logError(printf("sqlBindDuration: Duration not in allowed range.\n"););
1402       raise_error(RANGE_ERROR);
1403     } else {
1404     } /* if */
1405   } /* sqlBindDuration */
1406 
1407 
1408 
sqlBindFloat(sqlStmtType sqlStatement,intType pos,floatType value)1409 static void sqlBindFloat (sqlStmtType sqlStatement, intType pos, floatType value)
1410 
1411   {
1412     preparedStmtType preparedStmt;
1413 
1414   /* sqlBindFloat */
1415     logFunction(printf("sqlBindFloat(" FMT_U_MEM ", " FMT_D ", " FMT_E ")\n",
1416                        (memSizeType) sqlStatement, pos, value););
1417     preparedStmt = (preparedStmtType) sqlStatement;
1418     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1419       logError(printf("sqlBindFloat: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1420                       pos, preparedStmt->param_array_size););
1421       raise_error(RANGE_ERROR);
1422     } else {
1423       strDestr(preparedStmt->param_array[pos - 1].buffer);
1424       preparedStmt->param_array[pos - 1].buffer = fltStr(value);
1425     } /* if */
1426   } /* sqlBindFloat */
1427 
1428 
1429 
sqlBindInt(sqlStmtType sqlStatement,intType pos,intType value)1430 static void sqlBindInt (sqlStmtType sqlStatement, intType pos, intType value)
1431 
1432   {
1433     preparedStmtType preparedStmt;
1434 
1435   /* sqlBindInt */
1436     logFunction(printf("sqlBindInt(" FMT_U_MEM ", " FMT_D ", " FMT_D ")\n",
1437                        (memSizeType) sqlStatement, pos, value););
1438     preparedStmt = (preparedStmtType) sqlStatement;
1439     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1440       logError(printf("sqlBindInt: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1441                       pos, preparedStmt->param_array_size););
1442       raise_error(RANGE_ERROR);
1443     } else {
1444       strDestr(preparedStmt->param_array[pos - 1].buffer);
1445       preparedStmt->param_array[pos - 1].buffer = intStr(value);
1446     } /* if */
1447   } /* sqlBindInt */
1448 
1449 
1450 
sqlBindNull(sqlStmtType sqlStatement,intType pos)1451 static void sqlBindNull (sqlStmtType sqlStatement, intType pos)
1452 
1453   {
1454     preparedStmtType preparedStmt;
1455 
1456   /* sqlBindNull */
1457     logFunction(printf("sqlBindNull(" FMT_U_MEM ", " FMT_D ")\n",
1458                        (memSizeType) sqlStatement, pos););
1459     preparedStmt = (preparedStmtType) sqlStatement;
1460     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1461       logError(printf("sqlBindNull: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1462                       pos, preparedStmt->param_array_size););
1463       raise_error(RANGE_ERROR);
1464     } else {
1465       strDestr(preparedStmt->param_array[pos - 1].buffer);
1466       preparedStmt->param_array[pos - 1].buffer = cstri_to_stri("NULL");
1467       if (unlikely(preparedStmt->param_array[pos - 1].buffer == NULL)) {
1468         raise_error(MEMORY_ERROR);
1469       } /* if */
1470     } /* if */
1471   } /* sqlBindNull */
1472 
1473 
1474 
sqlBindStri(sqlStmtType sqlStatement,intType pos,const const_striType stri)1475 static void sqlBindStri (sqlStmtType sqlStatement, intType pos,
1476     const const_striType stri)
1477 
1478   {
1479     preparedStmtType preparedStmt;
1480 
1481   /* sqlBindStri */
1482     logFunction(printf("sqlBindStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
1483                        (memSizeType) sqlStatement, pos, striAsUnquotedCStri(stri)););
1484     preparedStmt = (preparedStmtType) sqlStatement;
1485     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1486       logError(printf("sqlBindStri: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1487                       pos, preparedStmt->param_array_size););
1488       raise_error(RANGE_ERROR);
1489     } else {
1490       strDestr(preparedStmt->param_array[pos - 1].buffer);
1491       preparedStmt->param_array[pos - 1].buffer = genSqlStringLiteral(stri);
1492     } /* if */
1493   } /* sqlBindStri */
1494 
1495 
1496 
sqlBindTime(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second,intType time_zone)1497 static void sqlBindTime (sqlStmtType sqlStatement, intType pos,
1498     intType year, intType month, intType day, intType hour,
1499     intType minute, intType second, intType micro_second,
1500     intType time_zone)
1501 
1502   {
1503     preparedStmtType preparedStmt;
1504     char timeLiteral[MAX_TIME_LITERAL_LENGTH + NULL_TERMINATION_LEN];
1505     memSizeType idx;
1506 
1507   /* sqlBindTime */
1508     logFunction(printf("sqlBindTime(" FMT_U_MEM ", " FMT_D ", "
1509                        F_D(04) "-" F_D(02) "-" F_D(02) " "
1510                        F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ", "
1511                        FMT_D ")\n",
1512                        (memSizeType) sqlStatement, pos,
1513                        year, month, day,
1514                        hour, minute, second, micro_second,
1515                        time_zone););
1516     preparedStmt = (preparedStmtType) sqlStatement;
1517     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
1518       logError(printf("sqlBindTime: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
1519                       pos, preparedStmt->param_array_size););
1520       raise_error(RANGE_ERROR);
1521     } else if (unlikely(year < -9999 || year > 9999 || month < 1 || month > 12 ||
1522                         day < 1 || day > 31 || hour < 0 || hour >= 24 ||
1523                         minute < 0 || minute >= 60 || second < 0 || second >= 60 ||
1524                         micro_second < 0 || micro_second >= 1000000)) {
1525       logError(printf("sqlBindTime: Time not in allowed range.\n"););
1526       raise_error(RANGE_ERROR);
1527     } else {
1528       if ((hour == 0 && minute == 0 && second == 0 && micro_second == 0) &&
1529           (year != 0 || month != 1 || day != 1)) {
1530         sprintf(timeLiteral, "'" F_D(04) "-" F_D(02) "-" F_D(02) "'",
1531                 year, month, day);
1532       } else {
1533         if (year == 0 && month == 1 && day == 1) {
1534           sprintf(timeLiteral, "'" F_D(02) ":" F_D(02) ":" F_D(02),
1535                   hour, minute, second);
1536         } else {
1537           sprintf(timeLiteral, "'" F_D(04) "-" F_D(02) "-" F_D(02)
1538                                " " F_D(02) ":" F_D(02) ":" F_D(02),
1539                   year, month, day, hour, minute, second);
1540         } /* if */
1541         if (micro_second == 0) {
1542           strcat(timeLiteral, "'");
1543         } else {
1544           sprintf(&timeLiteral[strlen(timeLiteral)], "." F_U(06),
1545                   micro_second);
1546           idx = strlen(timeLiteral);
1547           do {
1548             idx--;
1549           } while (timeLiteral[idx] == '0');
1550           timeLiteral[idx + 1] = '\'';
1551           timeLiteral[idx + 2] = '\0';
1552         } /* if */
1553       } /* if */
1554       strDestr(preparedStmt->param_array[pos - 1].buffer);
1555       preparedStmt->param_array[pos - 1].buffer = cstri_to_stri(timeLiteral);
1556       if (unlikely(preparedStmt->param_array[pos - 1].buffer == NULL)) {
1557         raise_error(MEMORY_ERROR);
1558       } /* if */
1559     } /* if */
1560   } /* sqlBindTime */
1561 
1562 
1563 
sqlClose(databaseType database)1564 static void sqlClose (databaseType database)
1565 
1566   {
1567     dbType db;
1568 
1569   /* sqlClose */
1570     logFunction(printf("sqlClose(" FMT_U_MEM ")\n",
1571                        (memSizeType) database););
1572     db = (dbType) database;
1573     if (db->dbproc != NULL) {
1574       dbclose(db->dbproc);
1575       db->dbproc = NULL;
1576     } /* if */
1577     logFunction(printf("sqlClose -->\n"););
1578   } /* sqlClose */
1579 
1580 
1581 
sqlColumnBigInt(sqlStmtType sqlStatement,intType column)1582 static bigIntType sqlColumnBigInt (sqlStmtType sqlStatement, intType column)
1583 
1584   {
1585     preparedStmtType preparedStmt;
1586     resultDataType columnData;
1587     BYTE *data;
1588     DBINT length;
1589     bigIntType columnValue;
1590 
1591   /* sqlColumnBigInt */
1592     logFunction(printf("sqlColumnBigInt(" FMT_U_MEM ", " FMT_D ")\n",
1593                        (memSizeType) sqlStatement, column););
1594     preparedStmt = (preparedStmtType) sqlStatement;
1595     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
1596                  (uintType) column > preparedStmt->result_array_size)) {
1597       logError(printf("sqlColumnBigInt: Fetch okay: %d, column: " FMT_D
1598                       ", max column: " FMT_U_MEM ".\n",
1599                       preparedStmt->fetchOkay, column,
1600                       preparedStmt->result_array_size););
1601       raise_error(RANGE_ERROR);
1602       columnValue = NULL;
1603     } else {
1604       columnData = &preparedStmt->result_array[column - 1];
1605       data = dbdata(preparedStmt->dbproc, (int) column);
1606       if (data == NULL) {
1607         length = dbdatlen(preparedStmt->dbproc, (int) column);
1608         if (likely(length == 0)) {
1609           columnValue = bigZero();
1610         } else {
1611           dbInconsistent("sqlColumnBigInt", "dbdatlen");
1612           logError(printf("sqlColumnBigInt: Column " FMT_D ": "
1613                           "dbdatlen returns %d.\n", column, length););
1614           raise_error(DATABASE_ERROR);
1615           columnValue = NULL;
1616         } /* if */
1617       } else {
1618         /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
1619         /* printf("buffer_type: %s\n",
1620            nameOfBufferType(columnData->buffer_type)); */
1621         switch (columnData->buffer_type) {
1622           case SYBINT1:
1623 #if SYBINT1_IS_SIGNED
1624             columnValue = bigFromInt32((int32Type) *(int8Type *) data);
1625 #else
1626             columnValue = bigFromInt32((int32Type) *(uint8Type *) data);
1627 #endif
1628             break;
1629           case SYBINT2:
1630             columnValue = bigFromInt32((int32Type) *(int16Type *) data);
1631             break;
1632           case SYBINT4:
1633             columnValue = bigFromInt32(*(int32Type *) data);
1634             break;
1635           case SYBINT8:
1636             columnValue = bigFromInt64(*(int64Type *) data);
1637             break;
1638           case SYBDECIMAL:
1639           case SYBNUMERIC:
1640             columnValue = getNumericBigInt(data);
1641             break;
1642           default:
1643             logError(printf("sqlColumnBigInt: Column " FMT_D " has the unknown type %s.\n",
1644                             column, nameOfBufferType(columnData->buffer_type)););
1645             raise_error(RANGE_ERROR);
1646             columnValue = NULL;
1647             break;
1648         } /* switch */
1649       } /* if */
1650     } /* if */
1651     logFunction(printf("sqlColumnBigInt --> %s\n", bigHexCStri(columnValue)););
1652     return columnValue;
1653   } /* sqlColumnBigInt */
1654 
1655 
1656 
sqlColumnBigRat(sqlStmtType sqlStatement,intType column,bigIntType * numerator,bigIntType * denominator)1657 static void sqlColumnBigRat (sqlStmtType sqlStatement, intType column,
1658     bigIntType *numerator, bigIntType *denominator)
1659 
1660   {
1661     preparedStmtType preparedStmt;
1662     resultDataType columnData;
1663     BYTE *data;
1664     DBINT length;
1665 
1666   /* sqlColumnBigRat */
1667     logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", *, *)\n",
1668                        (memSizeType) sqlStatement, column););
1669     preparedStmt = (preparedStmtType) sqlStatement;
1670     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
1671                  (uintType) column > preparedStmt->result_array_size)) {
1672       logError(printf("sqlColumnBigRat: Fetch okay: %d, column: " FMT_D
1673                       ", max column: " FMT_U_MEM ".\n",
1674                       preparedStmt->fetchOkay, column,
1675                       preparedStmt->result_array_size););
1676       raise_error(RANGE_ERROR);
1677     } else {
1678       columnData = &preparedStmt->result_array[column - 1];
1679       data = dbdata(preparedStmt->dbproc, (int) column);
1680       if (data == NULL) {
1681         length = dbdatlen(preparedStmt->dbproc, (int) column);
1682         if (likely(length == 0)) {
1683           *numerator = bigZero();
1684           *denominator = bigFromInt32(1);
1685         } else {
1686           dbInconsistent("sqlColumnBigRat", "dbdatlen");
1687           logError(printf("sqlColumnBigRat: Column " FMT_D ": "
1688                           "dbdatlen returns %d.\n", column, length););
1689           raise_error(DATABASE_ERROR);
1690         } /* if */
1691       } else {
1692         /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
1693         /* printf("buffer_type: %s\n",
1694            nameOfBufferType(columnData->buffer_type)); */
1695         switch (columnData->buffer_type) {
1696           case SYBINT1:
1697 #if SYBINT1_IS_SIGNED
1698             *numerator = bigFromInt32((int32Type) *(int8Type *) data);
1699 #else
1700             *numerator = bigFromInt32((int32Type) *(uint8Type *) data);
1701 #endif
1702             *denominator = bigFromInt32(1);
1703             break;
1704           case SYBINT2:
1705             *numerator = bigFromInt32((int32Type) *(int16Type *) data);
1706             *denominator = bigFromInt32(1);
1707             break;
1708           case SYBINT4:
1709             *numerator = bigFromInt32(*(int32Type *) data);
1710             *denominator = bigFromInt32(1);
1711             break;
1712           case SYBINT8:
1713             *numerator = bigFromInt64(*(int64Type *) data);
1714             *denominator = bigFromInt32(1);
1715             break;
1716           case SYBDECIMAL:
1717           case SYBNUMERIC:
1718             *numerator = getNumericBigRational(data, denominator);
1719             break;
1720           default:
1721             logError(printf("sqlColumnBigRat: Column " FMT_D " has the unknown type %s.\n",
1722                             column, nameOfBufferType(columnData->buffer_type)););
1723             raise_error(RANGE_ERROR);
1724             break;
1725         } /* switch */
1726       } /* if */
1727     } /* if */
1728     logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s) -->\n",
1729                        (memSizeType) sqlStatement, column,
1730                        bigHexCStri(*numerator), bigHexCStri(*denominator)););
1731   } /* sqlColumnBigRat */
1732 
1733 
1734 
sqlColumnBool(sqlStmtType sqlStatement,intType column)1735 static boolType sqlColumnBool (sqlStmtType sqlStatement, intType column)
1736 
1737   {
1738     preparedStmtType preparedStmt;
1739     resultDataType columnData;
1740     BYTE *data;
1741     DBINT length;
1742     intType columnValue;
1743 
1744   /* sqlColumnBool */
1745     logFunction(printf("sqlColumnBool(" FMT_U_MEM ", " FMT_D ")\n",
1746                        (memSizeType) sqlStatement, column););
1747     preparedStmt = (preparedStmtType) sqlStatement;
1748     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
1749                  (uintType) column > preparedStmt->result_array_size)) {
1750       logError(printf("sqlColumnBool: Fetch okay: %d, column: " FMT_D
1751                       ", max column: " FMT_U_MEM ".\n",
1752                       preparedStmt->fetchOkay, column,
1753                       preparedStmt->result_array_size););
1754       raise_error(RANGE_ERROR);
1755       columnValue = 0;
1756     } else {
1757       columnData = &preparedStmt->result_array[column - 1];
1758       data = dbdata(preparedStmt->dbproc, (int) column);
1759       if (data == NULL) {
1760         length = dbdatlen(preparedStmt->dbproc, (int) column);
1761         if (likely(length == 0)) {
1762           columnValue = 0;
1763         } else {
1764           dbInconsistent("sqlColumnBool", "dbdatlen");
1765           logError(printf("sqlColumnBool: Column " FMT_D ": "
1766                           "dbdatlen returns %d.\n", column, length););
1767           raise_error(DATABASE_ERROR);
1768           columnValue = 0;
1769         } /* if */
1770       } else {
1771         /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
1772         /* printf("buffer_type: %s\n",
1773            nameOfBufferType(columnData->buffer_type)); */
1774         switch (columnData->buffer_type) {
1775           case SYBINT1:
1776 #if SYBINT1_IS_SIGNED
1777             columnValue = *(int8Type *) data;
1778 #else
1779             columnValue = *(uint8Type *) data;
1780 #endif
1781             break;
1782           case SYBINT2:
1783             columnValue = *(int16Type *) data;
1784             break;
1785           case SYBINT4:
1786             columnValue = *(int32Type *) data;
1787             break;
1788           case SYBINT8:
1789             columnValue = *(int64Type *) data;
1790             break;
1791           case SYBDECIMAL:
1792           case SYBNUMERIC:
1793             columnValue = getNumericInt(data);
1794             break;
1795           case SYBCHAR:
1796           case SYBVARCHAR:
1797             length = dbdatlen(preparedStmt->dbproc, (int) column);
1798             /* printf("length: " FMT_D32 "\n", length); */
1799             if (length == -1) {
1800               columnValue = 0;
1801             } else if (unlikely(length != 1)) {
1802               logError(printf("sqlColumnBool: Column " FMT_D ": "
1803                               "The size of a boolean field must be 1.\n", column););
1804               raise_error(RANGE_ERROR);
1805               columnValue = 0;
1806             } else {
1807               columnValue = *(const_cstriType) data - '0';
1808             } /* if */
1809             break;
1810           default:
1811             logError(printf("sqlColumnBool: Column " FMT_D " has the unknown type %s.\n",
1812                             column, nameOfBufferType(columnData->buffer_type)););
1813             raise_error(RANGE_ERROR);
1814             columnValue = 0;
1815             break;
1816         } /* switch */
1817         if (unlikely((uintType) columnValue >= 2)) {
1818           logError(printf("sqlColumnBool: Column " FMT_D ": "
1819                           FMT_D " is not an allowed boolean value.\n",
1820                           column, columnValue););
1821           raise_error(RANGE_ERROR);
1822         } /* if */
1823       } /* if */
1824     } /* if */
1825     logFunction(printf("sqlColumnBool --> %s\n", columnValue ? "TRUE" : "FALSE"););
1826     return columnValue != 0;
1827   } /* sqlColumnBool */
1828 
1829 
1830 
sqlColumnBStri(sqlStmtType sqlStatement,intType column)1831 static bstriType sqlColumnBStri (sqlStmtType sqlStatement, intType column)
1832 
1833   {
1834     preparedStmtType preparedStmt;
1835     resultDataType columnData;
1836     DBINT length;
1837     bstriType columnValue;
1838 
1839   /* sqlColumnBStri */
1840     logFunction(printf("sqlColumnBStri(" FMT_U_MEM ", " FMT_D ")\n",
1841                        (memSizeType) sqlStatement, column););
1842     preparedStmt = (preparedStmtType) sqlStatement;
1843     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
1844                  (uintType) column > preparedStmt->result_array_size)) {
1845       logError(printf("sqlColumnBStri: Fetch okay: %d, column: " FMT_D
1846                       ", max column: " FMT_U_MEM ".\n",
1847                       preparedStmt->fetchOkay, column,
1848                       preparedStmt->result_array_size););
1849       raise_error(RANGE_ERROR);
1850       columnValue = NULL;
1851     } else {
1852       columnData = &preparedStmt->result_array[column - 1];
1853       /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
1854       /* printf("buffer_type: %s\n",
1855          nameOfBufferType(columnData->buffer_type)); */
1856       switch (columnData->buffer_type) {
1857         case SYBBINARY:
1858         case SYBVARBINARY:
1859           length = dbdatlen(preparedStmt->dbproc, (int) column);
1860           /* printf("length: " FMT_D32 "\n", length); */
1861           if (unlikely(length < 0)) {
1862             dbInconsistent("sqlColumnBStri", "dbdatlen");
1863             logError(printf("sqlColumnBStri: Column " FMT_D ": "
1864                             "dbdatlen returns %d.\n", column, length););
1865             raise_error(DATABASE_ERROR);
1866             columnValue = NULL;
1867           } else if (unlikely(!ALLOC_BSTRI_CHECK_SIZE(columnValue, (memSizeType) length))) {
1868             raise_error(MEMORY_ERROR);
1869           } else {
1870             columnValue->size = (memSizeType) length;
1871             memcpy(columnValue->mem,
1872                    (ustriType) dbdata(preparedStmt->dbproc, (int) column),
1873                    (memSizeType) length);
1874           } /* if */
1875           break;
1876         default:
1877           logError(printf("sqlColumnBStri: Column " FMT_D " has the unknown type %s.\n",
1878                           column, nameOfBufferType(columnData->buffer_type)););
1879           raise_error(RANGE_ERROR);
1880           columnValue = NULL;
1881           break;
1882       } /* switch */
1883     } /* if */
1884     logFunction(printf("sqlColumnBStri --> \"%s\"\n", bstriAsUnquotedCStri(columnValue)););
1885     return columnValue;
1886   } /* sqlColumnBStri */
1887 
1888 
1889 
sqlColumnDuration(sqlStmtType sqlStatement,intType column,intType * year,intType * month,intType * day,intType * hour,intType * minute,intType * second,intType * micro_second)1890 static void sqlColumnDuration (sqlStmtType sqlStatement, intType column,
1891     intType *year, intType *month, intType *day, intType *hour,
1892     intType *minute, intType *second, intType *micro_second)
1893 
1894   {
1895     preparedStmtType preparedStmt;
1896     resultDataType columnData;
1897     BYTE *data;
1898     DBINT length;
1899 
1900   /* sqlColumnDuration */
1901     logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ", *)\n",
1902                        (memSizeType) sqlStatement, column););
1903     preparedStmt = (preparedStmtType) sqlStatement;
1904     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
1905                  (uintType) column > preparedStmt->result_array_size)) {
1906       logError(printf("sqlColumnDuration: Fetch okay: %d, column: " FMT_D
1907                       ", max column: " FMT_U_MEM ".\n",
1908                       preparedStmt->fetchOkay, column,
1909                       preparedStmt->result_array_size););
1910       raise_error(RANGE_ERROR);
1911     } else {
1912       columnData = &preparedStmt->result_array[column - 1];
1913       data = dbdata(preparedStmt->dbproc, (int) column);
1914       if (data == NULL) {
1915         length = dbdatlen(preparedStmt->dbproc, (int) column);
1916         /* printf("length: " FMT_D32 "\n", length); */
1917         if (likely(length == 0)) {
1918           /* printf("Column is NULL -> Use default value: P0D\n"); */
1919           *year         = 0;
1920           *month        = 0;
1921           *day          = 0;
1922           *hour         = 0;
1923           *minute       = 0;
1924           *second       = 0;
1925           *micro_second = 0;
1926         } else {
1927           dbInconsistent("sqlColumnDuration", "dbdatlen");
1928           logError(printf("sqlColumnDuration: Column " FMT_D ": "
1929                           "dbdatlen returns %d.\n", column, length););
1930           raise_error(DATABASE_ERROR);
1931         } /* if */
1932       } else {
1933         /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
1934         /* printf("buffer_type: %s\n",
1935            nameOfBufferType(columnData->buffer_type)); */
1936         switch (columnData->buffer_type) {
1937           default:
1938             logError(printf("sqlColumnDuration: Column " FMT_D " has the unknown type %s.\n",
1939                             column, nameOfBufferType(columnData->buffer_type)););
1940             raise_error(RANGE_ERROR);
1941             break;
1942         } /* switch */
1943       } /* if */
1944     } /* if */
1945     logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ") --> P"
1946                                             FMT_D "Y" FMT_D "M" FMT_D "DT"
1947                                             FMT_D "H" FMT_D "M%s" FMT_U "." F_U(06) "S\n",
1948                        (memSizeType) sqlStatement, column,
1949                        *year, *month, *day, *hour, *minute,
1950                        *second < 0 || *micro_second < 0 ? "-" : "",
1951                        intAbs(*second), intAbs(*micro_second)););
1952   } /* sqlColumnDuration */
1953 
1954 
1955 
sqlColumnFloat(sqlStmtType sqlStatement,intType column)1956 static floatType sqlColumnFloat (sqlStmtType sqlStatement, intType column)
1957 
1958   {
1959     preparedStmtType preparedStmt;
1960     resultDataType columnData;
1961     BYTE *data;
1962     DBINT length;
1963     floatType columnValue;
1964 
1965   /* sqlColumnFloat */
1966     logFunction(printf("sqlColumnFloat(" FMT_U_MEM ", " FMT_D ")\n",
1967                        (memSizeType) sqlStatement, column););
1968     preparedStmt = (preparedStmtType) sqlStatement;
1969     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
1970                  (uintType) column > preparedStmt->result_array_size)) {
1971       logError(printf("sqlColumnFloat: Fetch okay: %d, column: " FMT_D
1972                       ", max column: " FMT_U_MEM ".\n",
1973                       preparedStmt->fetchOkay, column,
1974                       preparedStmt->result_array_size););
1975       raise_error(RANGE_ERROR);
1976       columnValue = 0.0;
1977     } else {
1978       columnData = &preparedStmt->result_array[column - 1];
1979       data = dbdata(preparedStmt->dbproc, (int) column);
1980       if (data == NULL) {
1981         length = dbdatlen(preparedStmt->dbproc, (int) column);
1982         if (likely(length == 0)) {
1983           columnValue = 0.0;
1984         } else {
1985           dbInconsistent("sqlColumnFloat", "dbdatlen");
1986           logError(printf("sqlColumnFloat: Column " FMT_D ": "
1987                           "dbdatlen returns %d.\n", column, length););
1988           raise_error(DATABASE_ERROR);
1989           columnValue = 0.0;
1990         } /* if */
1991       } else {
1992         /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
1993         /* printf("buffer_type: %s\n",
1994            nameOfBufferType(columnData->buffer_type)); */
1995         switch (columnData->buffer_type) {
1996           case SYBINT1:
1997 #if SYBINT1_IS_SIGNED
1998             columnValue = (floatType) *(int8Type *) data;
1999 #else
2000             columnValue = (floatType) *(uint8Type *) data;
2001 #endif
2002             break;
2003           case SYBINT2:
2004             columnValue = (floatType) *(int16Type *) data;
2005             break;
2006           case SYBINT4:
2007             columnValue = (floatType) *(int32Type *) data;
2008             break;
2009           case SYBINT8:
2010             columnValue = (floatType) *(int64Type *) data;
2011             break;
2012           case SYBREAL:
2013             columnValue = *(float *) data;
2014             break;
2015           case SYBFLT8:
2016             columnValue = *(double *) data;
2017             break;
2018           case SYBDECIMAL:
2019           case SYBNUMERIC:
2020             columnValue = getNumericFloat(data);
2021             break;
2022           default:
2023             logError(printf("sqlColumnFloat: Column " FMT_D " has the unknown type %s.\n",
2024                             column, nameOfBufferType(columnData->buffer_type)););
2025             raise_error(RANGE_ERROR);
2026             columnValue = 0.0;
2027             break;
2028         } /* switch */
2029       } /* if */
2030     } /* if */
2031     logFunction(printf("sqlColumnFloat --> " FMT_E "\n", columnValue););
2032     return columnValue;
2033   } /* sqlColumnFloat */
2034 
2035 
2036 
sqlColumnInt(sqlStmtType sqlStatement,intType column)2037 static intType sqlColumnInt (sqlStmtType sqlStatement, intType column)
2038 
2039   {
2040     preparedStmtType preparedStmt;
2041     resultDataType columnData;
2042     BYTE *data;
2043     DBINT length;
2044     intType columnValue;
2045 
2046   /* sqlColumnInt */
2047     logFunction(printf("sqlColumnInt(" FMT_U_MEM ", " FMT_D ")\n",
2048                        (memSizeType) sqlStatement, column););
2049     preparedStmt = (preparedStmtType) sqlStatement;
2050     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2051                  (uintType) column > preparedStmt->result_array_size)) {
2052       logError(printf("sqlColumnInt: Fetch okay: %d, column: " FMT_D
2053                       ", max column: " FMT_U_MEM ".\n",
2054                       preparedStmt->fetchOkay, column,
2055                       preparedStmt->result_array_size););
2056       raise_error(RANGE_ERROR);
2057       columnValue = 0;
2058     } else {
2059       columnData = &preparedStmt->result_array[column - 1];
2060       data = dbdata(preparedStmt->dbproc, (int) column);
2061       if (data == NULL) {
2062         length = dbdatlen(preparedStmt->dbproc, (int) column);
2063         if (likely(length == 0)) {
2064           columnValue = 0.0;
2065         } else {
2066           dbInconsistent("sqlColumnInt", "dbdatlen");
2067           logError(printf("sqlColumnInt: Column " FMT_D ": "
2068                           "dbdatlen returns %d.\n", column, length););
2069           raise_error(DATABASE_ERROR);
2070           columnValue = 0.0;
2071         } /* if */
2072       } else {
2073         /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
2074         /* printf("buffer_type: %s\n",
2075            nameOfBufferType(columnData->buffer_type)); */
2076         switch (columnData->buffer_type) {
2077           case SYBINT1:
2078 #if SYBINT1_IS_SIGNED
2079             columnValue = *(int8Type *) data;
2080 #else
2081             columnValue = *(uint8Type *) data;
2082 #endif
2083             break;
2084           case SYBINT2:
2085             columnValue = *(int16Type *) data;
2086             break;
2087           case SYBINT4:
2088             columnValue = *(int32Type *) data;
2089             break;
2090           case SYBINT8:
2091             columnValue = *(int64Type *) data;
2092             break;
2093           case SYBDECIMAL:
2094           case SYBNUMERIC:
2095             columnValue = getNumericInt(data);
2096             break;
2097           default:
2098             logError(printf("sqlColumnInt: Column " FMT_D " has the unknown type %s.\n",
2099                             column, nameOfBufferType(columnData->buffer_type)););
2100             raise_error(RANGE_ERROR);
2101             columnValue = 0;
2102             break;
2103         } /* switch */
2104       } /* if */
2105     } /* if */
2106     logFunction(printf("sqlColumnInt --> " FMT_D "\n", columnValue););
2107     return columnValue;
2108   } /* sqlColumnInt */
2109 
2110 
2111 
sqlColumnStri(sqlStmtType sqlStatement,intType column)2112 static striType sqlColumnStri (sqlStmtType sqlStatement, intType column)
2113 
2114   {
2115     preparedStmtType preparedStmt;
2116     resultDataType columnData;
2117     BYTE *data;
2118     DBINT length;
2119     errInfoType err_info = OKAY_NO_ERROR;
2120     striType columnValue;
2121 
2122   /* sqlColumnStri */
2123     logFunction(printf("sqlColumnStri(" FMT_U_MEM ", " FMT_D ")\n",
2124                        (memSizeType) sqlStatement, column););
2125     preparedStmt = (preparedStmtType) sqlStatement;
2126     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2127                  (uintType) column > preparedStmt->result_array_size)) {
2128       logError(printf("sqlColumnStri: Fetch okay: %d, column: " FMT_D
2129                       ", max column: " FMT_U_MEM ".\n",
2130                       preparedStmt->fetchOkay, column,
2131                       preparedStmt->result_array_size););
2132       raise_error(RANGE_ERROR);
2133       columnValue = NULL;
2134     } else {
2135       columnData = &preparedStmt->result_array[column - 1];
2136       data = dbdata(preparedStmt->dbproc, (int) column);
2137       /* printf("data: " FMT_U_MEM "\n", (memSizeType) data); */
2138       length = dbdatlen(preparedStmt->dbproc, (int) column);
2139       /* printf("length: " FMT_D32 "\n", length); */
2140       if (unlikely(length < 0)) {
2141         dbInconsistent("sqlColumnStri", "dbdatlen");
2142         logError(printf("sqlColumnStri: Column " FMT_D ": "
2143                         "dbdatlen returns %d.\n", column, length););
2144         raise_error(DATABASE_ERROR);
2145         columnValue = NULL;
2146       } else if (data == NULL) {
2147         if (likely(length == 0)) {
2148           columnValue = strEmpty();
2149         } else {
2150           dbInconsistent("sqlColumnStri", "dbdatlen");
2151           logError(printf("sqlColumnStri: Column " FMT_D ": "
2152                           "dbdatlen returns %d.\n", column, length););
2153           raise_error(DATABASE_ERROR);
2154           columnValue = NULL;
2155         } /* if */
2156       } else {
2157         /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
2158         /* printf("buffer_type: %s\n",
2159            nameOfBufferType(columnData->buffer_type)); */
2160         switch (columnData->buffer_type) {
2161           case SYBCHAR:
2162             while (length > 0 && data[length - 1] == ' ') {
2163               length--;
2164             } /* if */
2165             columnValue = cstri8_buf_to_stri((const_cstriType) data,
2166                 (memSizeType) length, &err_info);
2167             if (unlikely(columnValue == NULL)) {
2168               raise_error(err_info);
2169             } /* if */
2170             break;
2171           case SYBVARCHAR:
2172             columnValue = cstri8_buf_to_stri((const_cstriType) data,
2173                 (memSizeType) length, &err_info);
2174             if (unlikely(columnValue == NULL)) {
2175               raise_error(err_info);
2176             } /* if */
2177             break;
2178           case SYBBINARY:
2179           case SYBVARBINARY:
2180             if (unlikely(!ALLOC_STRI_CHECK_SIZE(columnValue, (memSizeType) length))) {
2181               raise_error(MEMORY_ERROR);
2182             } else {
2183               memcpy_to_strelem(columnValue->mem, (ustriType) data,
2184                   (memSizeType) length);
2185               columnValue->size = (memSizeType) length;
2186             } /* if */
2187             break;
2188           default:
2189             logError(printf("sqlColumnStri: Column " FMT_D " has the unknown type %s.\n",
2190                             column, nameOfBufferType(columnData->buffer_type)););
2191             raise_error(RANGE_ERROR);
2192             columnValue = NULL;
2193             break;
2194         } /* switch */
2195       } /* if */
2196     } /* if */
2197     logFunction(printf("sqlColumnStri --> \"%s\"\n", striAsUnquotedCStri(columnValue)););
2198     return columnValue;
2199   } /* sqlColumnStri */
2200 
2201 
2202 
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)2203 static void sqlColumnTime (sqlStmtType sqlStatement, intType column,
2204     intType *year, intType *month, intType *day, intType *hour,
2205     intType *minute, intType *second, intType *micro_second,
2206     intType *time_zone, boolType *is_dst)
2207 
2208   {
2209     preparedStmtType preparedStmt;
2210     resultDataType columnData;
2211     BYTE *data;
2212     DBINT length;
2213     DBDATETIMEALL *dateTimeAll;
2214     uint64Type numTimeUnits;
2215     errInfoType err_info = OKAY_NO_ERROR;
2216 
2217   /* sqlColumnTime */
2218     logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", *)\n",
2219                        (memSizeType) sqlStatement, column););
2220     preparedStmt = (preparedStmtType) sqlStatement;
2221     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2222                  (uintType) column > preparedStmt->result_array_size)) {
2223       logError(printf("sqlColumnTime: Fetch okay: %d, column: " FMT_D
2224                       ", max column: " FMT_U_MEM ".\n",
2225                       preparedStmt->fetchOkay, column,
2226                       preparedStmt->result_array_size););
2227       raise_error(RANGE_ERROR);
2228     } else {
2229       columnData = &preparedStmt->result_array[column - 1];
2230       data = dbdata(preparedStmt->dbproc, (int) column);
2231       if (data == NULL) {
2232         length = dbdatlen(preparedStmt->dbproc, (int) column);
2233         /* printf("length: " FMT_D32 "\n", length); */
2234         if (likely(length == 0)) {
2235           /* printf("Column is NULL -> Use default value: 0-01-01 00:00:00\n"); */
2236           *year         = 0;
2237           *month        = 1;
2238           *day          = 1;
2239           *hour         = 0;
2240           *minute       = 0;
2241           *second       = 0;
2242           *micro_second = 0;
2243           *time_zone    = 0;
2244           *is_dst       = 0;
2245         } else {
2246           dbInconsistent("sqlColumnTime", "dbdatlen");
2247           logError(printf("sqlColumnTime: Column " FMT_D ": "
2248                           "dbdatlen returns %d.\n", column, length););
2249           raise_error(DATABASE_ERROR);
2250         } /* if */
2251       } else {
2252         /* printf("buffer: %s\n", (unsigned char *) columnData->buffer); */
2253         /* printf("buffer_type: %s\n",
2254            nameOfBufferType(columnData->buffer_type)); */
2255         switch (columnData->buffer_type) {
2256           case SYBMSDATE:
2257           case SYBMSTIME:
2258           case SYBMSDATETIME2:
2259             length = dbdatlen(preparedStmt->dbproc, (int) column);
2260             /* printf("length: " FMT_D32 "\n", length); */
2261             if (unlikely(length < 0)) {
2262               dbInconsistent("sqlColumnTime", "dbdatlen");
2263               logError(printf("sqlColumnTime: Column " FMT_D ": "
2264                               "dbdatlen returns %d.\n", column, length););
2265               raise_error(DATABASE_ERROR);
2266             } else if (unlikely(length != sizeof(DBDATETIMEALL))) {
2267               logError(printf("sqlColumnTime: In column " FMT_D
2268                               " the DBDATETIMEALL length of " FMT_D32 " is wrong.\n",
2269                               column, length););
2270               err_info = RANGE_ERROR;
2271             } else {
2272               dateTimeAll = (DBDATETIMEALL *) data;
2273               if (columnData->buffer_type == SYBMSTIME) {
2274                 *year = 0;
2275                 *month = 1;
2276                 *day = 1;
2277               } else {
2278                 dateFromDaysSince1900(dateTimeAll->date, year, month, day);
2279               } /* if */
2280               *micro_second = (intType) ((dateTimeAll->time % 10000000) / 10);
2281               numTimeUnits = dateTimeAll->time / 10000000;
2282               *second = (intType) (numTimeUnits % 60);
2283               numTimeUnits /= 60;
2284               *minute = (intType) (numTimeUnits % 60);
2285               *hour = (intType) (numTimeUnits / 60);
2286             } /* if */
2287             if (unlikely(err_info != OKAY_NO_ERROR)) {
2288               raise_error(err_info);
2289             } /* if */
2290             break;
2291           default:
2292             logError(printf("sqlColumnTime: Column " FMT_D " has the unknown type %s.\n",
2293                             column, nameOfBufferType(columnData->buffer_type)););
2294             raise_error(RANGE_ERROR);
2295             break;
2296         } /* switch */
2297       } /* if */
2298     } /* if */
2299     logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", "
2300                                         F_D(04) "-" F_D(02) "-" F_D(02) " "
2301                                         F_D(02) ":" F_D(02) ":" F_D(02) "."
2302                                         F_D(06) ", " FMT_D ", %d) -->\n",
2303                        (memSizeType) sqlStatement, column,
2304                        *year, *month, *day, *hour, *minute, *second,
2305                        *micro_second, *time_zone, *is_dst););
2306   } /* sqlColumnTime */
2307 
2308 
2309 
sqlCommit(databaseType database)2310 static void sqlCommit (databaseType database)
2311 
2312   {
2313     dbType db;
2314     errInfoType err_info = OKAY_NO_ERROR;
2315 
2316   /* sqlCommit */
2317     logFunction(printf("sqlCommit(" FMT_U_MEM ")\n",
2318                        (memSizeType) database););
2319     db = (dbType) database;
2320     if (unlikely(db->dbproc == NULL)) {
2321       logError(printf("sqlCommit: Database is not open.\n"););
2322       raise_error(RANGE_ERROR);
2323     } else if (!db->autoCommit) {
2324       doExecute(db->dbproc, "COMMIT", &err_info);
2325       doExecute(db->dbproc, "BEGIN TRANSACTION", &err_info);
2326       if (unlikely(err_info != OKAY_NO_ERROR)) {
2327         raise_error(err_info);
2328       } /* if */
2329     } /* if */
2330     logFunction(printf("sqlCommit -->\n"););
2331   } /* sqlCommit */
2332 
2333 
2334 
sqlExecute(sqlStmtType sqlStatement)2335 static void sqlExecute (sqlStmtType sqlStatement)
2336 
2337   {
2338     preparedStmtType preparedStmt;
2339     striType boundStatement;
2340     cstriType query;
2341     RETCODE retCode;
2342     errInfoType err_info = OKAY_NO_ERROR;
2343 
2344   /* sqlExecute */
2345     logFunction(printf("sqlExecute(" FMT_U_MEM ")\n",
2346                        (memSizeType) sqlStatement););
2347     preparedStmt = (preparedStmtType) sqlStatement;
2348     boundStatement = getBoundStatement(preparedStmt, &err_info);
2349     if (unlikely(boundStatement == NULL)) {
2350       if (err_info == RANGE_ERROR) {
2351         dbLibError("sqlExecute", "SQLExecute",
2352                    "Unbound statement parameter(s).\n");
2353         raise_error(DATABASE_ERROR);
2354       } else {
2355         raise_error(err_info);
2356       } /* if */
2357     } else {
2358       query = stri_to_cstri8(boundStatement, &err_info);
2359       if (likely(query != NULL)) {
2360         /* printf("ppStmt: " FMT_X_MEM "\n", (memSizeType) preparedStmt->ppStmt); */
2361         preparedStmt->fetchOkay = FALSE;
2362         if (unlikely(dbcmd(preparedStmt->dbproc, query) != SUCCEED)) {
2363           logError(printf("sqlExecute: dbcmd(" FMT_U_MEM ", \"%s\") failed.\n",
2364                           (memSizeType) preparedStmt->dbproc, query););
2365           preparedStmt->executeSuccessful = FALSE;
2366           err_info = DATABASE_ERROR;
2367         } else if (unlikely(dbsqlexec(preparedStmt->dbproc) != SUCCEED)) {
2368           logError(printf("sqlExecute: dbsqlexec(" FMT_U_MEM ") with \"%s\" failed.\n",
2369                           (memSizeType) preparedStmt->dbproc, query););
2370           preparedStmt->executeSuccessful = FALSE;
2371           err_info = DATABASE_ERROR;
2372         } else {
2373           retCode = dbresults(preparedStmt->dbproc);
2374           /* printf("dbresults returns: %d\n", retCode); */
2375           if (unlikely(retCode == FAIL)) {
2376             logError(printf("sqlExecute: dbresults() failed.\n"););
2377             preparedStmt->executeSuccessful = FALSE;
2378             err_info = DATABASE_ERROR;
2379           } else {
2380             preparedStmt->executeSuccessful = TRUE;
2381             preparedStmt->fetchFinished = FALSE;
2382             err_info = setupResult(preparedStmt);
2383           } /* if */
2384         } /* if */
2385         free_cstri8(query, boundStatement);
2386       } /* if */
2387       FREE_STRI(boundStatement, boundStatement->size);
2388       if (unlikely(err_info != OKAY_NO_ERROR)) {
2389         raise_error(err_info);
2390       } /* if */
2391     } /* if */
2392     logFunction(printf("sqlExecute -->\n"););
2393   } /* sqlExecute */
2394 
2395 
2396 
sqlFetch(sqlStmtType sqlStatement)2397 static boolType sqlFetch (sqlStmtType sqlStatement)
2398 
2399   {
2400     preparedStmtType preparedStmt;
2401     RETCODE fetch_result;
2402 
2403   /* sqlFetch */
2404     logFunction(printf("sqlFetch(" FMT_U_MEM ")\n",
2405                        (memSizeType) sqlStatement););
2406     preparedStmt = (preparedStmtType) sqlStatement;
2407     if (unlikely(!preparedStmt->executeSuccessful)) {
2408       dbLibError("sqlFetch", "OCIStmtExecute",
2409                  "Execute was not successful.\n");
2410       logError(printf("sqlFetch: Execute was not successful.\n"););
2411       preparedStmt->fetchOkay = FALSE;
2412       raise_error(DATABASE_ERROR);
2413     } else {
2414       fetch_result = dbnextrow(preparedStmt->dbproc);
2415       /* printf("fetch_result: %d\n", fetch_result); */
2416       if (fetch_result == NO_MORE_ROWS) {
2417         preparedStmt->fetchOkay = FALSE;
2418         preparedStmt->fetchFinished = TRUE;
2419       } else {
2420         preparedStmt->fetchOkay = TRUE;
2421       } /* if */
2422     } /* if */
2423     logFunction(printf("sqlFetch --> %d\n", preparedStmt->fetchOkay););
2424     return preparedStmt->fetchOkay;
2425   } /* sqlFetch */
2426 
2427 
2428 
sqlGetAutoCommit(databaseType database)2429 static boolType sqlGetAutoCommit (databaseType database)
2430 
2431   {
2432     dbType db;
2433     boolType autoCommit;
2434 
2435   /* sqlGetAutoCommit */
2436     logFunction(printf("sqlGetAutoCommit(" FMT_U_MEM ")\n",
2437                        (memSizeType) database););
2438     db = (dbType) database;
2439     if (unlikely(db->dbproc == NULL)) {
2440       logError(printf("sqlGetAutoCommit: Database is not open.\n"););
2441       raise_error(RANGE_ERROR);
2442       autoCommit = FALSE;
2443     } else {
2444       autoCommit = db->autoCommit;
2445     } /* if */
2446     logFunction(printf("sqlGetAutoCommit --> %d\n", autoCommit););
2447     return autoCommit;
2448   } /* sqlGetAutoCommit */
2449 
2450 
2451 
sqlIsNull(sqlStmtType sqlStatement,intType column)2452 static boolType sqlIsNull (sqlStmtType sqlStatement, intType column)
2453 
2454   {
2455     preparedStmtType preparedStmt;
2456     boolType isNull;
2457 
2458   /* sqlIsNull */
2459     logFunction(printf("sqlIsNull(" FMT_U_MEM ", " FMT_D ")\n",
2460                        (memSizeType) sqlStatement, column););
2461     preparedStmt = (preparedStmtType) sqlStatement;
2462     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2463                  (uintType) column > preparedStmt->result_array_size)) {
2464       logError(printf("sqlIsNull: Fetch okay: %d, column: " FMT_D
2465                       ", max column: " FMT_U_MEM ".\n",
2466                       preparedStmt->fetchOkay, column,
2467                       preparedStmt->result_array_size););
2468       raise_error(RANGE_ERROR);
2469       isNull = FALSE;
2470     } else {
2471       isNull = dbdatlen(preparedStmt->dbproc, (int) column) == 0;
2472     } /* if */
2473     logFunction(printf("sqlIsNull --> %s\n", isNull ? "TRUE" : "FALSE"););
2474     return isNull;
2475   } /* sqlIsNull */
2476 
2477 
2478 
sqlPrepare(databaseType database,const const_striType sqlStatementStri)2479 static sqlStmtType sqlPrepare (databaseType database,
2480     const const_striType sqlStatementStri)
2481 
2482   {
2483     dbType db;
2484     striType *stmtPartArray;
2485     memSizeType numBindParameters;
2486     errInfoType err_info = OKAY_NO_ERROR;
2487     preparedStmtType preparedStmt;
2488 
2489   /* sqlPrepare */
2490     logFunction(printf("sqlPrepare(" FMT_U_MEM ", \"%s\")\n",
2491                        (memSizeType) database,
2492                        striAsUnquotedCStri(sqlStatementStri)););
2493     db = (dbType) database;
2494     if (unlikely(db->dbproc == NULL)) {
2495       logError(printf("sqlPrepare: Database is not open.\n"););
2496       err_info = RANGE_ERROR;
2497       preparedStmt = NULL;
2498     } else {
2499       stmtPartArray = processStatementStri(sqlStatementStri, &numBindParameters, &err_info);
2500       if (stmtPartArray == NULL) {
2501         preparedStmt = NULL;
2502       } else {
2503         if (!ALLOC_RECORD2(preparedStmt, preparedStmtRecord,
2504                            count.prepared_stmt, count.prepared_stmt_bytes)) {
2505           err_info = MEMORY_ERROR;
2506         } else {
2507           memset(preparedStmt, 0, sizeof(preparedStmtRecord));
2508           preparedStmt->usage_count = 1;
2509           preparedStmt->sqlFunc = db->sqlFunc;
2510           preparedStmt->dbproc = db->dbproc;
2511           preparedStmt->stmtPartArray = stmtPartArray;
2512           err_info = setStmtPartArrayCharCount(preparedStmt, numBindParameters);
2513           if (likely(err_info == OKAY_NO_ERROR)) {
2514             err_info = setupParameters(preparedStmt, numBindParameters);
2515           } /* if */
2516           if (unlikely(err_info != OKAY_NO_ERROR)) {
2517             freePreparedStmt((sqlStmtType) preparedStmt);
2518             preparedStmt = NULL;
2519           } /* if */
2520         } /* if */
2521       } /* if */
2522     } /* if */
2523     if (unlikely(err_info != OKAY_NO_ERROR)) {
2524       raise_error(err_info);
2525     } /* if */
2526     logFunction(printf("sqlPrepare --> " FMT_U_MEM "\n",
2527                        (memSizeType) preparedStmt););
2528     return (sqlStmtType) preparedStmt;
2529   } /* sqlPrepare */
2530 
2531 
2532 
sqlRollback(databaseType database)2533 static void sqlRollback (databaseType database)
2534 
2535   {
2536     dbType db;
2537     errInfoType err_info = OKAY_NO_ERROR;
2538 
2539   /* sqlRollback */
2540     logFunction(printf("sqlRollback(" FMT_U_MEM ")\n",
2541                        (memSizeType) database););
2542     db = (dbType) database;
2543     if (unlikely(db->dbproc == NULL)) {
2544       logError(printf("sqlRollback: Database is not open.\n"););
2545       raise_error(RANGE_ERROR);
2546     } else if (!db->autoCommit) {
2547       doExecute(db->dbproc, "ROLLBACK", &err_info);
2548       doExecute(db->dbproc, "BEGIN TRANSACTION", &err_info);
2549       if (unlikely(err_info != OKAY_NO_ERROR)) {
2550         raise_error(err_info);
2551       } /* if */
2552     } /* if */
2553     logFunction(printf("sqlRollback -->\n"););
2554   } /* sqlRollback */
2555 
2556 
2557 
sqlSetAutoCommit(databaseType database,boolType autoCommit)2558 static void sqlSetAutoCommit (databaseType database, boolType autoCommit)
2559 
2560   {
2561     dbType db;
2562     errInfoType err_info = OKAY_NO_ERROR;
2563 
2564   /* sqlSetAutoCommit */
2565     logFunction(printf("sqlSetAutoCommit(" FMT_U_MEM ", %d)\n",
2566                        (memSizeType) database, autoCommit););
2567     db = (dbType) database;
2568     if (unlikely(db->dbproc == NULL)) {
2569       logError(printf("sqlSetAutoCommit: Database is not open.\n"););
2570       raise_error(RANGE_ERROR);
2571     } else {
2572       if (db->autoCommit != autoCommit) {
2573         if (autoCommit) {
2574           doExecute(db->dbproc, "COMMIT", &err_info);
2575         } else {
2576           doExecute(db->dbproc, "BEGIN TRANSACTION", &err_info);
2577         } /* if */
2578         if (unlikely(err_info != OKAY_NO_ERROR)) {
2579           raise_error(err_info);
2580         } else {
2581           db->autoCommit = autoCommit;
2582         } /* if */
2583       } /* if */
2584     } /* if */
2585     logFunction(printf("sqlSetAutoCommit -->\n"););
2586   } /* sqlSetAutoCommit */
2587 
2588 
2589 
sqlStmtColumnCount(sqlStmtType sqlStatement)2590 static intType sqlStmtColumnCount (sqlStmtType sqlStatement)
2591 
2592   {
2593     preparedStmtType preparedStmt;
2594     intType columnCount;
2595 
2596   /* sqlStmtColumnCount */
2597     logFunction(printf("sqlStmtColumnCount(" FMT_U_MEM ")\n",
2598                        (memSizeType) sqlStatement););
2599     preparedStmt = (preparedStmtType) sqlStatement;
2600     if (unlikely(preparedStmt->result_array_size > INTTYPE_MAX)) {
2601       logError(printf("sqlStmtColumnCount: "
2602                       "result_array_size (=" FMT_U_MEM ") > INTTYPE_MAX\n",
2603                       preparedStmt->result_array_size););
2604       raise_error(RANGE_ERROR);
2605       columnCount = 0;
2606     } else {
2607       columnCount = (intType) preparedStmt->result_array_size;
2608     } /* if */
2609     logFunction(printf("sqlStmtColumnCount --> " FMT_D "\n", columnCount););
2610     return columnCount;
2611   } /* sqlStmtColumnCount */
2612 
2613 
2614 
sqlStmtColumnName(sqlStmtType sqlStatement,intType column)2615 static striType sqlStmtColumnName (sqlStmtType sqlStatement, intType column)
2616 
2617   {
2618     preparedStmtType preparedStmt;
2619     char *columnName;
2620     errInfoType err_info = OKAY_NO_ERROR;
2621     striType name;
2622 
2623   /* sqlStmtColumnName */
2624     logFunction(printf("sqlStmtColumnName(" FMT_U_MEM ", " FMT_D ")\n",
2625                        (memSizeType) sqlStatement, column););
2626     preparedStmt = (preparedStmtType) sqlStatement;
2627     if (unlikely(column < 1 ||
2628                  (uintType) column > preparedStmt->result_array_size)) {
2629       logError(printf("sqlStmtColumnName: column: " FMT_D
2630                       ", max column: " FMT_U_MEM ".\n",
2631                       column, preparedStmt->result_array_size););
2632       err_info = RANGE_ERROR;
2633       name = NULL;
2634     } else {
2635       columnName = dbcolname(preparedStmt->dbproc, (int) column);
2636       if (unlikely(columnName == NULL)) {
2637         dbLibError("sqlStmtColumnName", "dbcolname", "dbcolname() returns NULL.\n");
2638         logError(printf("sqlStmtColumnName: dbcolname() returns NULL.\n"););
2639         err_info = DATABASE_ERROR;
2640         name = NULL;
2641       } else {
2642         name = cstri8_to_stri(columnName, &err_info);
2643       } /* if */
2644     } /* if */
2645     if (unlikely(name == NULL)) {
2646       raise_error(err_info);
2647     } /* if */
2648     logFunction(printf("sqlStmtColumnName --> \"%s\"\n",
2649                        striAsUnquotedCStri(name)););
2650     return name;
2651   } /* sqlStmtColumnName */
2652 
2653 
2654 
setupFuncTable(void)2655 static boolType setupFuncTable (void)
2656 
2657   { /* setupFuncTable */
2658     if (sqlFunc == NULL) {
2659       if (ALLOC_RECORD(sqlFunc, sqlFuncRecord, count.sql_func)) {
2660         memset(sqlFunc, 0, sizeof(sqlFuncRecord));
2661         sqlFunc->freeDatabase       = &freeDatabase;
2662         sqlFunc->freePreparedStmt   = &freePreparedStmt;
2663         sqlFunc->sqlBindBigInt      = &sqlBindBigInt;
2664         sqlFunc->sqlBindBigRat      = &sqlBindBigRat;
2665         sqlFunc->sqlBindBool        = &sqlBindBool;
2666         sqlFunc->sqlBindBStri       = &sqlBindBStri;
2667         sqlFunc->sqlBindDuration    = &sqlBindDuration;
2668         sqlFunc->sqlBindFloat       = &sqlBindFloat;
2669         sqlFunc->sqlBindInt         = &sqlBindInt;
2670         sqlFunc->sqlBindNull        = &sqlBindNull;
2671         sqlFunc->sqlBindStri        = &sqlBindStri;
2672         sqlFunc->sqlBindTime        = &sqlBindTime;
2673         sqlFunc->sqlClose           = &sqlClose;
2674         sqlFunc->sqlColumnBigInt    = &sqlColumnBigInt;
2675         sqlFunc->sqlColumnBigRat    = &sqlColumnBigRat;
2676         sqlFunc->sqlColumnBool      = &sqlColumnBool;
2677         sqlFunc->sqlColumnBStri     = &sqlColumnBStri;
2678         sqlFunc->sqlColumnDuration  = &sqlColumnDuration;
2679         sqlFunc->sqlColumnFloat     = &sqlColumnFloat;
2680         sqlFunc->sqlColumnInt       = &sqlColumnInt;
2681         sqlFunc->sqlColumnStri      = &sqlColumnStri;
2682         sqlFunc->sqlColumnTime      = &sqlColumnTime;
2683         sqlFunc->sqlCommit          = &sqlCommit;
2684         sqlFunc->sqlExecute         = &sqlExecute;
2685         sqlFunc->sqlFetch           = &sqlFetch;
2686         sqlFunc->sqlGetAutoCommit   = &sqlGetAutoCommit;
2687         sqlFunc->sqlIsNull          = &sqlIsNull;
2688         sqlFunc->sqlPrepare         = &sqlPrepare;
2689         sqlFunc->sqlRollback        = &sqlRollback;
2690         sqlFunc->sqlSetAutoCommit   = &sqlSetAutoCommit;
2691         sqlFunc->sqlStmtColumnCount = &sqlStmtColumnCount;
2692         sqlFunc->sqlStmtColumnName  = &sqlStmtColumnName;
2693       } /* if */
2694     } /* if */
2695     if (quoteQuote == NULL) {
2696       quoteQuote = CSTRI_LITERAL_TO_STRI("''");
2697     } /* if */
2698     return sqlFunc != NULL;
2699   } /* setupFuncTable */
2700 
2701 
2702 
sqlOpenTds(const const_striType host,intType port,const const_striType dbName,const const_striType user,const const_striType password)2703 databaseType sqlOpenTds (const const_striType host, intType port,
2704     const const_striType dbName, const const_striType user,
2705     const const_striType password)
2706 
2707   {
2708     const_cstriType host8;
2709     memSizeType host8Length;
2710     const_cstriType dbName8;
2711     const_cstriType user8;
2712     const_cstriType password8;
2713     char portName[1 + INTTYPE_DECIMAL_SIZE + NULL_TERMINATION_LEN];
2714     memSizeType portNameLength;
2715     cstriType hostAndPort = NULL;
2716     const_cstriType server;
2717     LOGINREC *login;
2718     DBPROCESS *dbproc;
2719     RETCODE erc;
2720     errInfoType err_info = OKAY_NO_ERROR;
2721     dbType database;
2722 
2723   /* sqlOpenTds */
2724     logFunction(printf("sqlOpenTds(\"%s\", ",
2725                        striAsUnquotedCStri(host));
2726                 printf(FMT_D ", \"%s\", ",
2727                        port, striAsUnquotedCStri(dbName));
2728                 printf("\"%s\", ", striAsUnquotedCStri(user));
2729                 printf("\"%s\")\n", striAsUnquotedCStri(password)););
2730     if (!findDll()) {
2731       logError(printf("sqlOpenTds: findDll() failed\n"););
2732       err_info = DATABASE_ERROR;
2733       database = NULL;
2734     } else if (unlikely((host8 = stri_to_cstri8(host, &err_info)) == NULL)) {
2735       database = NULL;
2736     } else {
2737       if (port == 0) {
2738         server = host8;
2739       } else {
2740         host8Length = strlen(host8);
2741         portNameLength = (memSizeType) sprintf(portName, ":" FMT_D, port);
2742         if (unlikely(!ALLOC_CSTRI(hostAndPort, host8Length + portNameLength))) {
2743           err_info = MEMORY_ERROR;
2744           database = NULL;
2745         } else {
2746           memcpy(hostAndPort, host8, host8Length);
2747           memcpy(&hostAndPort[host8Length], portName,
2748                  portNameLength + NULL_TERMINATION_LEN);
2749           server = hostAndPort;
2750         } /* if */
2751       } /* if */
2752       if (likely(err_info == OKAY_NO_ERROR)) {
2753         dbName8 = stri_to_cstri8(dbName, &err_info);
2754         if (unlikely(dbName8 == NULL)) {
2755           database = NULL;
2756         } else {
2757           user8 = stri_to_cstri8(user, &err_info);
2758           if (unlikely(user8 == NULL)) {
2759             database = NULL;
2760           } else {
2761             password8 = stri_to_cstri8(password, &err_info);
2762             if (unlikely(password8 == NULL)) {
2763               database = NULL;
2764             } else {
2765               if (dbinit() == FAIL) {
2766                 dbLibError("sqlOpenTds", "dbinit", "dbinit() failed.\n");
2767                 logError(printf("sqlOpenTds: dbinit() failed.\n"););
2768                 err_info = DATABASE_ERROR;
2769                 database = NULL;
2770               } else {
2771                 dberrhandle(err_handler);
2772                 dbmsghandle(msg_handler);
2773                 if ((login = dblogin()) == NULL) {
2774                   setDbErrorMsg("sqlOpenTds", "dblogin");
2775                   logError(printf("sqlOpenTds: dblogin() failed.\n%s\n",
2776                                   dbError.message););
2777                   err_info = MEMORY_ERROR;
2778                   database = NULL;
2779                 } else {
2780                   if (server[0] != '\0') {
2781                     DBSETLHOST(login, server);
2782                   } /* if */
2783                   DBSETLUSER(login, user8);
2784                   DBSETLPWD(login, password8);
2785                   DBSETLCHARSET(login, "UTF-8");
2786                   if ((dbproc = dbopen(login, server)) == NULL) {
2787                     setDbErrorMsg("sqlOpenTds", "dbopen");
2788                     logError(printf("sqlOpenTds: dbopen(\"%s\"/\"***Pwd***\", \"%s\"):\n%s\n",
2789                                     user8, server, dbError.message););
2790                     err_info = DATABASE_ERROR;
2791                     dbexit();
2792                     database = NULL;
2793                   } else if ((erc = dbuse(dbproc, dbName8)) == FAIL) {
2794                     setDbErrorMsg("sqlOpenTds", "dbuse");
2795                     logError(printf("sqlOpenTds: dbuse(*, \"%s\"):\n%s\n",
2796                                     dbName8, dbError.message););
2797                     err_info = DATABASE_ERROR;
2798                     dbclose(dbproc);
2799                     dbexit();
2800                     database = NULL;
2801                   } else {
2802                     /* CHAR fields are padded with spaces up to the field  */
2803                     /* width and all spaces are retrieved. For VARCHAR     */
2804                     /* fields trailing spaces are stored and retrieved.    */
2805                     doExecute(dbproc, "SET ANSI_PADDING ON", &err_info);
2806                     /* Set the default nullability of new created columns. */
2807                     /* By default connections from DB-Library applications */
2808                     /* create non nullable columns. This is changed such   */
2809                     /* that nullable columns are created by default.       */
2810                     doExecute(dbproc, "SET ANSI_NULL_DFLT_ON ON", &err_info);
2811                     /* Identifiers can be delimited by double quotation    */
2812                     /* marks ("), and literals must be delimited by single */
2813                     /* quotation marks (').                                */
2814                     doExecute(dbproc, "SET QUOTED_IDENTIFIER ON", &err_info);
2815                     /* Terminate a query if an overflow or divide-by-zero  */
2816                     /* error occurs during query execution.                */
2817                     doExecute(dbproc, "SET ARITHABORT ON", &err_info);
2818                     /* Specify the size of varchar(max), nvarchar(max) and */
2819                     /* varbinary(max) returned by a SELECT statement.      */
2820                     /* The default value would be 4 KB. Unlimited is -1.   */
2821                     doExecute(dbproc, "SET TEXTSIZE -1", &err_info);
2822                     if (unlikely(err_info != OKAY_NO_ERROR)) {
2823                       dbclose(dbproc);
2824                       dbexit();
2825                       database = NULL;
2826                     } else if (unlikely(!setupFuncTable() ||
2827                                         !ALLOC_RECORD2(database, dbRecord,
2828                                                        count.database,
2829                                                        count.database_bytes))) {
2830                       err_info = MEMORY_ERROR;
2831                       dbclose(dbproc);
2832                       dbexit();
2833                       database = NULL;
2834                     } else {
2835                       memset(database, 0, sizeof(dbRecord));
2836                       database->usage_count = 1;
2837                       database->sqlFunc = sqlFunc;
2838                       database->driver = DB_CATEGORY_TDS;
2839                       database->dbproc = dbproc;
2840                       database->autoCommit = TRUE;
2841                     } /* if */
2842                   } /* if */
2843                   dbloginfree(login);
2844                 } /* if */
2845               } /* if */
2846               free_cstri8(password8, password);
2847             } /* if */
2848             free_cstri8(user8, user);
2849           } /* if */
2850           free_cstri8(dbName8, dbName);
2851         } /* if */
2852       } /* if */
2853       if (hostAndPort != NULL) {
2854         UNALLOC_CSTRI(hostAndPort, host8Length + portNameLength);
2855       } /* if */
2856       free_cstri8(host8, host);
2857     } /* if */
2858     if (unlikely(err_info != OKAY_NO_ERROR)) {
2859       raise_error(err_info);
2860     } /* if */
2861     logFunction(printf("sqlOpenTds --> " FMT_U_MEM "\n",
2862                        (memSizeType) database););
2863     return (databaseType) database;
2864   } /* sqlOpenTds */
2865 
2866 #else
2867 
2868 
2869 
sqlOpenTds(const const_striType host,intType port,const const_striType dbName,const const_striType user,const const_striType password)2870 databaseType sqlOpenTds (const const_striType host, intType port,
2871     const const_striType dbName, const const_striType user,
2872     const const_striType password)
2873 
2874   { /* sqlOpenTds */
2875     logError(printf("sqlOpenTds(\"%s\", ",
2876                     striAsUnquotedCStri(host));
2877              printf(FMT_D ", \"%s\", ",
2878                     port, striAsUnquotedCStri(dbName));
2879              printf("\"%s\", ", striAsUnquotedCStri(user));
2880              printf("\"%s\"): TDS driver not present.\n",
2881                     striAsUnquotedCStri(password)););
2882     raise_error(RANGE_ERROR);
2883     return NULL;
2884   } /* sqlOpenTds */
2885 
2886 #endif
2887