1 /********************************************************************/
2 /*                                                                  */
3 /*  sql_fire.c    Database access functions for Firebird/InterBase. */
4 /*  Copyright (C) 1989 - 2019  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_fire.c                                      */
27 /*  Changes: 2018, 2019  Thomas Mertes                              */
28 /*  Content: Database access functions for Firebird/InterBase.      */
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 "limits.h"
41 #include "time.h"
42 #ifdef FIRE_INCLUDE
43 #include FIRE_INCLUDE
44 #endif
45 
46 #include "common.h"
47 #include "data_rtl.h"
48 #include "striutl.h"
49 #include "heaputl.h"
50 #include "numutl.h"
51 #include "str_rtl.h"
52 #include "flt_rtl.h"
53 #include "tim_rtl.h"
54 #include "cmd_rtl.h"
55 #include "big_drv.h"
56 #include "rtl_err.h"
57 #include "dll_drv.h"
58 #include "sql_base.h"
59 #include "sql_drv.h"
60 
61 #ifdef FIRE_INCLUDE
62 
63 
64 typedef struct {
65     uintType      usage_count;
66     sqlFuncType   sqlFunc;
67     intType       driver;
68     isc_db_handle connection;
69     isc_tr_handle trans_handle;
70   } dbRecord, *dbType;
71 
72 typedef struct {
73     boolType     bound;
74   } bindDataRecord, *bindDataType;
75 
76 typedef struct {
77     uintType        usage_count;
78     sqlFuncType     sqlFunc;
79     dbType          db;
80     isc_stmt_handle ppStmt;
81     XSQLDA         *in_sqlda;
82     XSQLDA         *out_sqlda;
83     bindDataType    param_array;
84     int             statement_type;
85     boolType        executeSuccessful;
86     boolType        fetchOkay;
87     boolType        fetchFinished;
88   } preparedStmtRecord, *preparedStmtType;
89 
90 typedef struct {
91     memSizeType fileName8Length;
92     cstriType fileName8;
93     memSizeType user8Length;
94     const_cstriType user8;
95     memSizeType password8Length;
96     const_cstriType password8;
97 } loginRecord, *loginType;
98 
99 static sqlFuncType sqlFunc = NULL;
100 
101 static char isc_tbp[] = {isc_tpb_version3, isc_tpb_write,
102                          isc_tpb_concurrency, isc_tpb_wait};
103 static char type_item[] = {isc_info_sql_stmt_type};
104 
105 #ifndef SQL_BOOLEAN
106 #define SQL_BOOLEAN   32764
107 #endif
108 
109 
110 #ifdef FIRE_DLL
111 
112 #ifndef STDCALL
113 #if defined(_WIN32) && HAS_STDCALL
114 #define STDCALL __stdcall
115 #else
116 #define STDCALL
117 #endif
118 #endif
119 
120 typedef ISC_STATUS (STDCALL *tp_isc_attach_database) (ISC_STATUS *status_vector,
121                                                       short db_name_length,
122                                                       char *db_name,
123                                                       isc_db_handle *db_handle,
124                                                       short parm_buffer_length,
125                                                       char *parm_buffer);
126 typedef ISC_STATUS (STDCALL *tp_isc_blob_info) (ISC_STATUS *status_vector,
127                                                 isc_blob_handle *blob_handle,
128                                                 short item_list_buffer_length,
129                                                 char *item_list_buffer,
130                                                 short result_buffer_length,
131                                                 char *result_buffer);
132 typedef ISC_STATUS (STDCALL *tp_isc_close_blob) (ISC_STATUS *status_vector,
133                                                  isc_blob_handle *blob_handle);
134 typedef ISC_STATUS (STDCALL *tp_isc_commit_transaction) (ISC_STATUS *status_vector,
135                                                          isc_tr_handle *trans_handle);
136 typedef ISC_STATUS (STDCALL *tp_isc_create_blob2) (ISC_STATUS *status_vector,
137                                                    isc_db_handle *db_handle,
138                                                    isc_tr_handle *trans_handle,
139                                                    isc_blob_handle *blob_handle,
140                                                    ISC_QUAD *blob_id,
141                                                    short bpb_length,
142                                                    char *bpb_address);
143 typedef ISC_STATUS (STDCALL *tp_isc_create_database) (ISC_STATUS *status_vector,
144                                                       short db_name_length,
145                                                       char *db_name,
146                                                       isc_db_handle *db_handle,
147                                                       short parm_buffer_length,
148                                                       char *parm_buffer,
149                                                       short db_type);
150 typedef void (STDCALL *tp_isc_decode_sql_date) (ISC_DATE *ib_date,
151                                                 void *tm_date);
152 typedef void (STDCALL *tp_isc_decode_sql_time) (ISC_TIME *ib_time,
153                                                 void *tm_date);
154 typedef void (STDCALL *tp_isc_decode_timestamp) (ISC_TIMESTAMP *ib_date,
155                                                  void *tm_date);
156 typedef ISC_STATUS (STDCALL *tp_isc_detach_database) (ISC_STATUS *status_vector,
157                                                       isc_db_handle *db_handle);
158 typedef ISC_STATUS (STDCALL *tp_isc_dsql_allocate_statement) (ISC_STATUS *status_vector,
159                                                               isc_db_handle *db_handle,
160                                                               isc_stmt_handle *stmt_handle);
161 typedef ISC_STATUS (STDCALL *tp_isc_dsql_describe) (ISC_STATUS *status_vector,
162                                                     isc_stmt_handle *stmt_handle,
163                                                     unsigned short da_version,
164                                                     XSQLDA *xsqlda);
165 typedef ISC_STATUS (STDCALL *tp_isc_dsql_describe_bind) (ISC_STATUS *status_vector,
166                                                          isc_stmt_handle *stmt_handle,
167                                                          unsigned short da_version,
168                                                          XSQLDA *xsqlda);
169 typedef ISC_STATUS (STDCALL *tp_isc_dsql_execute2) (ISC_STATUS *status_vector,
170                                                     isc_tr_handle *trans_handle,
171                                                     isc_stmt_handle *stmt_handle,
172                                                     unsigned short da_version,
173                                                     XSQLDA *in_xsqlda,
174                                                     XSQLDA *out_xsqlda);
175 typedef ISC_STATUS (STDCALL *tp_isc_dsql_fetch) (ISC_STATUS *status_vector,
176                                                  isc_stmt_handle *stmt_handle,
177                                                  unsigned short da_version,
178                                                  XSQLDA *xsqlda);
179 typedef ISC_STATUS (STDCALL *tp_isc_dsql_free_statement) (ISC_STATUS *status_vector,
180                                                           isc_stmt_handle *stmt_handle,
181                                                           unsigned short option);
182 typedef ISC_STATUS (STDCALL *tp_isc_dsql_prepare) (ISC_STATUS *status_vector,
183                                                    isc_tr_handle *trans_handle,
184                                                    isc_stmt_handle *stmt_handle,
185                                                    unsigned short length,
186                                                    char *statement,
187                                                    unsigned short dialect,
188                                                    XSQLDA *xsqlda);
189 typedef ISC_STATUS (STDCALL *tp_isc_dsql_sql_info) (ISC_STATUS *status_vector,
190                                                     isc_stmt_handle *stmt_handle,
191                                                     unsigned short item_length,
192                                                     char *items,
193                                                     unsigned short buffer_length,
194                                                     char *buffer);
195 typedef void (STDCALL *tp_isc_encode_sql_date) (void *tm_date,
196                                                 ISC_DATE *ib_date);
197 typedef void (STDCALL *tp_isc_encode_sql_time) (void *tm_date,
198                                                 ISC_TIME *ib_time);
199 typedef void (STDCALL *tp_isc_encode_timestamp) (void *tm_date,
200                                                  ISC_TIMESTAMP *ib_timestamp);
201 typedef ISC_STATUS (STDCALL *tp_isc_get_segment) (ISC_STATUS *status_vector,
202                                                   isc_blob_handle *blob_handle,
203                                                   unsigned short *actual_seg_length,
204                                                   unsigned short seg_buffer_length,
205                                                   char *seg_buffer);
206 typedef ISC_STATUS (STDCALL *tp_isc_interprete) (char *buffer, ISC_STATUS **status_vector);
207 typedef ISC_STATUS (STDCALL *tp_isc_open_blob2) (ISC_STATUS *status_vector,
208                                                  isc_db_handle *db_handle,
209                                                  isc_tr_handle *trans_handle,
210                                                  isc_blob_handle *blob_handle,
211                                                  ISC_QUAD *blob_id,
212                                                  short bpb_length,
213                                                  char *bpb_address);
214 typedef ISC_INT64 (STDCALL *tp_isc_portable_integer) (char *buffer,
215                                                       short length);
216 typedef ISC_STATUS (STDCALL *tp_isc_print_status) (ISC_STATUS *status_vector);
217 typedef ISC_STATUS (STDCALL *tp_isc_put_segment) (ISC_STATUS *status_vector,
218                                                   isc_blob_handle *blob_handle,
219                                                   unsigned short seg_buffer_length,
220                                                   char *seg_buffer);
221 typedef ISC_STATUS (STDCALL *tp_isc_rollback_transaction) (ISC_STATUS *status_vector,
222                                                            isc_tr_handle *trans_handle);
223 typedef ISC_STATUS (STDCALL *tp_isc_start_transaction) (ISC_STATUS *status_vector,
224                                                         isc_tr_handle *trans_handle,
225                                                         short db_handle_count,
226                                                         isc_db_handle *db_handle,
227                                                         unsigned short tpb_length,
228                                                         char *tpb_address);
229 
230 static tp_isc_attach_database         ptr_isc_attach_database;
231 static tp_isc_blob_info               ptr_isc_blob_info;
232 static tp_isc_close_blob              ptr_isc_close_blob;
233 static tp_isc_commit_transaction      ptr_isc_commit_transaction;
234 static tp_isc_create_blob2            ptr_isc_create_blob2;
235 static tp_isc_create_database         ptr_isc_create_database;
236 static tp_isc_decode_sql_date         ptr_isc_decode_sql_date;
237 static tp_isc_decode_sql_time         ptr_isc_decode_sql_time;
238 static tp_isc_decode_timestamp        ptr_isc_decode_timestamp;
239 static tp_isc_detach_database         ptr_isc_detach_database;
240 static tp_isc_dsql_allocate_statement ptr_isc_dsql_allocate_statement;
241 static tp_isc_dsql_describe           ptr_isc_dsql_describe;
242 static tp_isc_dsql_describe_bind      ptr_isc_dsql_describe_bind;
243 static tp_isc_dsql_execute2           ptr_isc_dsql_execute2;
244 static tp_isc_dsql_fetch              ptr_isc_dsql_fetch;
245 static tp_isc_dsql_free_statement     ptr_isc_dsql_free_statement;
246 static tp_isc_dsql_prepare            ptr_isc_dsql_prepare;
247 static tp_isc_dsql_sql_info           ptr_isc_dsql_sql_info;
248 static tp_isc_encode_sql_date         ptr_isc_encode_sql_date;
249 static tp_isc_encode_sql_time         ptr_isc_encode_sql_time;
250 static tp_isc_encode_timestamp        ptr_isc_encode_timestamp;
251 static tp_isc_get_segment             ptr_isc_get_segment;
252 static tp_isc_interprete              ptr_isc_interprete;
253 static tp_isc_open_blob2              ptr_isc_open_blob2;
254 static tp_isc_portable_integer        ptr_isc_portable_integer;
255 static tp_isc_print_status            ptr_isc_print_status;
256 static tp_isc_put_segment             ptr_isc_put_segment;
257 static tp_isc_rollback_transaction    ptr_isc_rollback_transaction;
258 static tp_isc_start_transaction       ptr_isc_start_transaction;
259 
260 #define isc_attach_database         ptr_isc_attach_database
261 #define isc_blob_info               ptr_isc_blob_info
262 #define isc_close_blob              ptr_isc_close_blob
263 #define isc_commit_transaction      ptr_isc_commit_transaction
264 #define isc_create_blob2            ptr_isc_create_blob2
265 #define isc_create_database         ptr_isc_create_database
266 #define isc_decode_sql_date         ptr_isc_decode_sql_date
267 #define isc_decode_sql_time         ptr_isc_decode_sql_time
268 #define isc_decode_timestamp        ptr_isc_decode_timestamp
269 #define isc_detach_database         ptr_isc_detach_database
270 #define isc_dsql_allocate_statement ptr_isc_dsql_allocate_statement
271 #define isc_dsql_describe           ptr_isc_dsql_describe
272 #define isc_dsql_describe_bind      ptr_isc_dsql_describe_bind
273 #define isc_dsql_execute2           ptr_isc_dsql_execute2
274 #define isc_dsql_fetch              ptr_isc_dsql_fetch
275 #define isc_dsql_free_statement     ptr_isc_dsql_free_statement
276 #define isc_dsql_prepare            ptr_isc_dsql_prepare
277 #define isc_dsql_sql_info           ptr_isc_dsql_sql_info
278 #define isc_encode_sql_date         ptr_isc_encode_sql_date
279 #define isc_encode_sql_time         ptr_isc_encode_sql_time
280 #define isc_encode_timestamp        ptr_isc_encode_timestamp
281 #define isc_get_segment             ptr_isc_get_segment
282 #define isc_interprete              ptr_isc_interprete
283 #define isc_open_blob2              ptr_isc_open_blob2
284 #define isc_portable_integer        ptr_isc_portable_integer
285 #define isc_print_status            ptr_isc_print_status
286 #define isc_put_segment             ptr_isc_put_segment
287 #define isc_rollback_transaction    ptr_isc_rollback_transaction
288 #define isc_start_transaction       ptr_isc_start_transaction
289 
290 
291 
setupDll(const char * dllName)292 static boolType setupDll (const char *dllName)
293 
294   {
295     static void *dbDll = NULL;
296 
297   /* setupDll */
298     logFunction(printf("setupDll(\"%s\")\n", dllName););
299     if (dbDll == NULL) {
300       dbDll = dllOpen(dllName);
301       if (dbDll != NULL) {
302         if ((isc_attach_database         = (tp_isc_attach_database)         dllFunc(dbDll, "isc_attach_database"))         == NULL ||
303             (isc_blob_info               = (tp_isc_blob_info)               dllFunc(dbDll, "isc_blob_info"))               == NULL ||
304             (isc_close_blob              = (tp_isc_close_blob)              dllFunc(dbDll, "isc_close_blob"))              == NULL ||
305             (isc_commit_transaction      = (tp_isc_commit_transaction)      dllFunc(dbDll, "isc_commit_transaction"))      == NULL ||
306             (isc_create_blob2            = (tp_isc_create_blob2)            dllFunc(dbDll, "isc_create_blob2"))            == NULL ||
307             (isc_create_database         = (tp_isc_create_database)         dllFunc(dbDll, "isc_create_database"))         == NULL ||
308             (isc_decode_sql_date         = (tp_isc_decode_sql_date)         dllFunc(dbDll, "isc_decode_sql_date"))         == NULL ||
309             (isc_decode_sql_time         = (tp_isc_decode_sql_time)         dllFunc(dbDll, "isc_decode_sql_time"))         == NULL ||
310             (isc_decode_timestamp        = (tp_isc_decode_timestamp)        dllFunc(dbDll, "isc_decode_timestamp"))        == NULL ||
311             (isc_detach_database         = (tp_isc_detach_database)         dllFunc(dbDll, "isc_detach_database"))         == NULL ||
312             (isc_dsql_allocate_statement = (tp_isc_dsql_allocate_statement) dllFunc(dbDll, "isc_dsql_allocate_statement")) == NULL ||
313             (isc_dsql_describe           = (tp_isc_dsql_describe)           dllFunc(dbDll, "isc_dsql_describe"))           == NULL ||
314             (isc_dsql_describe_bind      = (tp_isc_dsql_describe_bind)      dllFunc(dbDll, "isc_dsql_describe_bind"))      == NULL ||
315             (isc_dsql_execute2           = (tp_isc_dsql_execute2)           dllFunc(dbDll, "isc_dsql_execute2"))           == NULL ||
316             (isc_dsql_fetch              = (tp_isc_dsql_fetch)              dllFunc(dbDll, "isc_dsql_fetch"))              == NULL ||
317             (isc_dsql_free_statement     = (tp_isc_dsql_free_statement)     dllFunc(dbDll, "isc_dsql_free_statement"))     == NULL ||
318             (isc_dsql_prepare            = (tp_isc_dsql_prepare)            dllFunc(dbDll, "isc_dsql_prepare"))            == NULL ||
319             (isc_dsql_sql_info           = (tp_isc_dsql_sql_info)           dllFunc(dbDll, "isc_dsql_sql_info"))           == NULL ||
320             (isc_encode_sql_date         = (tp_isc_encode_sql_date)         dllFunc(dbDll, "isc_encode_sql_date"))         == NULL ||
321             (isc_encode_sql_time         = (tp_isc_encode_sql_time)         dllFunc(dbDll, "isc_encode_sql_time"))         == NULL ||
322             (isc_encode_timestamp        = (tp_isc_encode_timestamp)        dllFunc(dbDll, "isc_encode_timestamp"))        == NULL ||
323             (isc_get_segment             = (tp_isc_get_segment)             dllFunc(dbDll, "isc_get_segment"))             == NULL ||
324             (isc_interprete              = (tp_isc_interprete)              dllFunc(dbDll, "isc_interprete"))              == NULL ||
325             (isc_open_blob2              = (tp_isc_open_blob2)              dllFunc(dbDll, "isc_open_blob2"))              == NULL ||
326             (isc_portable_integer        = (tp_isc_portable_integer)        dllFunc(dbDll, "isc_portable_integer"))        == NULL ||
327             (isc_print_status            = (tp_isc_print_status)            dllFunc(dbDll, "isc_print_status"))            == NULL ||
328             (isc_put_segment             = (tp_isc_put_segment)             dllFunc(dbDll, "isc_put_segment"))             == NULL ||
329             (isc_rollback_transaction    = (tp_isc_rollback_transaction)    dllFunc(dbDll, "isc_rollback_transaction"))    == NULL ||
330             (isc_start_transaction       = (tp_isc_start_transaction)       dllFunc(dbDll, "isc_start_transaction"))       == NULL) {
331           dbDll = NULL;
332         } /* if */
333       } /* if */
334     } /* if */
335     logFunction(printf("setupDll --> %d\n", dbDll != NULL););
336     return dbDll != NULL;
337   } /* setupDll */
338 
339 
340 
findDll(void)341 static boolType findDll (void)
342 
343   {
344     const char *dllList[] = { FIRE_DLL };
345     unsigned int pos;
346     boolType found = FALSE;
347 
348   /* findDll */
349     for (pos = 0; pos < sizeof(dllList) / sizeof(char *) && !found; pos++) {
350       found = setupDll(dllList[pos]);
351     } /* for */
352     if (!found) {
353       dllErrorMessage("sqlOpenFire", "findDll", dllList,
354                       sizeof(dllList) / sizeof(char *));
355     } /* if */
356     return found;
357   } /* findDll */
358 
359 #else
360 
361 #define findDll() TRUE
362 
363 #endif
364 
365 
366 
setDbErrorMsg(const char * funcName,const char * dbFuncName,ISC_STATUS * status_vector)367 static void setDbErrorMsg (const char *funcName, const char *dbFuncName,
368     ISC_STATUS *status_vector)
369 
370   {
371     ISC_STATUS *pvector;
372     char messageText[512];
373 
374   /* setDbErrorMsg */
375     dbError.funcName = funcName;
376     dbError.dbFuncName = dbFuncName;
377     dbError.errorCode = 0;
378     pvector = status_vector;
379     isc_interprete(messageText, &pvector);
380     strcpy(dbError.message, messageText);
381     messageText[0] = '\n';
382     messageText[1] = '-';
383     while (isc_interprete(&messageText[2], &pvector) != 0) {
384       strcat(dbError.message, messageText);
385     } /* while */
386   } /* setDbErrorMsg */
387 
388 
389 
390 static void sqlClose (databaseType database);
391 
392 
393 
394 /**
395  *  Closes a database and frees the memory used by it.
396  */
freeDatabase(databaseType database)397 static void freeDatabase (databaseType database)
398 
399   {
400     dbType db;
401 
402   /* freeDatabase */
403     logFunction(printf("freeDatabase(" FMT_U_MEM ")\n",
404                        (memSizeType) database););
405     sqlClose(database);
406     db = (dbType) database;
407     FREE_RECORD2(db, dbRecord, count.database, count.database_bytes);
408     logFunction(printf("freeDatabase -->\n"););
409   } /* freeDatabase */
410 
411 
412 
413 /**
414  *  Closes a prepared statement and frees the memory used by it.
415  */
freePreparedStmt(sqlStmtType sqlStatement)416 static void freePreparedStmt (sqlStmtType sqlStatement)
417 
418   {
419     preparedStmtType preparedStmt;
420     ISC_STATUS status_vector[20];
421     int column;
422     int numColumns;
423     XSQLVAR *var;
424 
425   /* freePreparedStmt */
426     logFunction(printf("freePreparedStmt(" FMT_U_MEM ")\n",
427                        (memSizeType) sqlStatement););
428     preparedStmt = (preparedStmtType) sqlStatement;
429     if (preparedStmt->ppStmt != 0) {
430       if (unlikely((isc_dsql_free_statement(status_vector,
431                                             &preparedStmt->ppStmt,
432                                             DSQL_drop),
433                     status_vector[0] == 1 && status_vector[1] != 0))) {
434         setDbErrorMsg("freePreparedStmt", "isc_dsql_free_statement",
435                       status_vector);
436         logError(printf("freePreparedStmt: isc_dsql_free_statement error:\n%s\n",
437                         dbError.message););
438         raise_error(DATABASE_ERROR);
439       } /* if */
440     } /* if */
441     if (preparedStmt->in_sqlda != NULL) {
442       numColumns = preparedStmt->in_sqlda->sqld;
443       for (column = 0, var = preparedStmt->in_sqlda->sqlvar;
444            column < numColumns; column++, var++) {
445         free(var->sqldata);
446         free(var->sqlind);
447       } /* for */
448       free(preparedStmt->in_sqlda);
449     } /* if */
450     if (preparedStmt->out_sqlda != NULL) {
451       numColumns = preparedStmt->out_sqlda->sqld;
452       for (column = 0, var = preparedStmt->out_sqlda->sqlvar;
453            column < numColumns; column++, var++) {
454         free(var->sqldata);
455         free(var->sqlind);
456       } /* for */
457       free(preparedStmt->out_sqlda);
458     } /* if */
459     if (preparedStmt->param_array != NULL) {
460       FREE_TABLE(preparedStmt->param_array, bindDataRecord,
461                  (memSizeType) preparedStmt->in_sqlda->sqld);
462     } /* if */
463     FREE_RECORD2(preparedStmt, preparedStmtRecord,
464                  count.prepared_stmt, count.prepared_stmt_bytes);
465     logFunction(printf("freePreparedStmt -->\n"););
466   } /* freePreparedStmt */
467 
468 
469 
470 #if LOG_FUNCTIONS_EVERYWHERE || LOG_FUNCTIONS || VERBOSE_EXCEPTIONS_EVERYWHERE || VERBOSE_EXCEPTIONS
nameOfSqlType(int dtype)471 static const char *nameOfSqlType (int dtype)
472 
473   {
474     static char buffer[50];
475     const char *typeName;
476 
477   /* nameOfSqlType */
478     logFunction(printf("nameOfSqlType(%d)\n", dtype););
479     switch (dtype) {
480       case SQL_TEXT:      typeName = "SQL_TEXT";      break;
481       case SQL_VARYING:   typeName = "SQL_VARYING";   break;
482       case SQL_SHORT:     typeName = "SQL_SHORT";     break;
483       case SQL_LONG:      typeName = "SQL_LONG";      break;
484       case SQL_FLOAT:     typeName = "SQL_FLOAT";     break;
485       case SQL_DOUBLE:    typeName = "SQL_DOUBLE";    break;
486       case SQL_D_FLOAT:   typeName = "SQL_D_FLOAT";   break;
487       case SQL_TIMESTAMP: typeName = "SQL_TIMESTAMP"; break;
488       case SQL_BLOB:      typeName = "SQL_BLOB";      break;
489       case SQL_ARRAY:     typeName = "SQL_ARRAY";     break;
490       case SQL_QUAD:      typeName = "SQL_QUAD";      break;
491       case SQL_TYPE_TIME: typeName = "SQL_TYPE_TIME"; break;
492       case SQL_TYPE_DATE: typeName = "SQL_TYPE_DATE"; break;
493       case SQL_INT64:     typeName = "SQL_INT64";     break;
494       case SQL_BOOLEAN:   typeName = "SQL_BOOLEAN";   break;
495       case SQL_NULL:      typeName = "SQL_NULL";      break;
496       default:
497         sprintf(buffer, "%d", dtype);
498         typeName = buffer;
499         break;
500     } /* switch */
501     logFunction(printf("nameOfSqlType --> %s\n", typeName););
502     return typeName;
503   } /* nameOfSqlType */
504 #endif
505 
506 
507 
assign_in_sqlda(preparedStmtType preparedStmt)508 static errInfoType assign_in_sqlda (preparedStmtType preparedStmt)
509 
510   {
511     XSQLDA *in_sqlda;
512     ISC_STATUS status_vector[20];
513     errInfoType err_info = OKAY_NO_ERROR;
514 
515   /* assign_in_sqlda */
516     in_sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(1));
517     if (unlikely(in_sqlda == NULL)) {
518       err_info = MEMORY_ERROR;
519     } else {
520       memset(in_sqlda, 0, XSQLDA_LENGTH(1));
521       in_sqlda->version = SQLDA_VERSION1;
522       in_sqlda->sqln = 1;
523       if ((isc_dsql_describe_bind(status_vector,
524           &preparedStmt->ppStmt, 1, in_sqlda),
525           status_vector[0] == 1 && status_vector[1] != 0)) {
526         setDbErrorMsg("sqlPrepare", "isc_dsql_describe_bind",
527                       status_vector);
528         logError(printf("sqlPrepare: isc_dsql_describe_bind error:\n%s\n",
529                         dbError.message););
530         free(in_sqlda);
531         err_info = DATABASE_ERROR;
532       } else {
533         if (in_sqlda->sqld > in_sqlda->sqln) {
534           short numInVars = in_sqlda->sqld;
535           free(in_sqlda);
536           in_sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH((memSizeType) numInVars));
537           if (unlikely(in_sqlda == NULL)) {
538             err_info = MEMORY_ERROR;
539           } else {
540             memset(in_sqlda, 0, XSQLDA_LENGTH((memSizeType) numInVars));
541             in_sqlda->version = SQLDA_VERSION1;
542             in_sqlda->sqln = numInVars;
543             if ((isc_dsql_describe_bind(status_vector,
544                 &preparedStmt->ppStmt, 1, in_sqlda),
545                 status_vector[0] == 1 && status_vector[1] != 0)) {
546               setDbErrorMsg("sqlPrepare", "isc_dsql_describe_bind",
547                             status_vector);
548               logError(printf("sqlPrepare: isc_dsql_describe_bind error:\n%s\n",
549                               dbError.message););
550               free(in_sqlda);
551               err_info = DATABASE_ERROR;
552             } else {
553               preparedStmt->in_sqlda = in_sqlda;
554             } /* if */
555           } /* if */
556         } else {
557           preparedStmt->in_sqlda = in_sqlda;
558         } /* if */
559       } /* if */
560     } /* if */
561     return err_info;
562   } /* assign_in_sqlda */
563 
564 
565 
assign_out_sqlda(preparedStmtType preparedStmt,XSQLDA * out_sqlda)566 static errInfoType assign_out_sqlda (preparedStmtType preparedStmt,
567     XSQLDA *out_sqlda)
568 
569   {
570     ISC_STATUS status_vector[20];
571     errInfoType err_info = OKAY_NO_ERROR;
572 
573   /* assign_out_sqlda */
574     if (out_sqlda->sqld > out_sqlda->sqln) {
575       short numOutVars = out_sqlda->sqld;
576       free(out_sqlda);
577       out_sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH((memSizeType) numOutVars));
578       if (unlikely(out_sqlda == NULL)) {
579         err_info = MEMORY_ERROR;
580       } else {
581         memset(out_sqlda, 0, XSQLDA_LENGTH((memSizeType) numOutVars));
582         out_sqlda->version = SQLDA_VERSION1;
583         out_sqlda->sqln = numOutVars;
584         if ((isc_dsql_describe(status_vector, &preparedStmt->ppStmt,
585             1, out_sqlda),
586             status_vector[0] == 1 && status_vector[1] != 0)) {
587           setDbErrorMsg("sqlPrepare", "isc_dsql_describe",
588                         status_vector);
589           logError(printf("sqlPrepare: isc_dsql_describe error:\n%s\n",
590                           dbError.message););
591           free(out_sqlda);
592           err_info = DATABASE_ERROR;
593         } else {
594           preparedStmt->out_sqlda = out_sqlda;
595         } /* if */
596       } /* if */
597     } else {
598       preparedStmt->out_sqlda = out_sqlda;
599     } /* if */
600     return err_info;
601   } /* assign_out_sqlda */
602 
603 
604 
setupParameters(preparedStmtType preparedStmt)605 static errInfoType setupParameters (preparedStmtType preparedStmt)
606 
607   {
608     int column;
609     int numColumns;
610     XSQLVAR *sqlvar;
611     int dtype;
612     errInfoType err_info = OKAY_NO_ERROR;
613 
614   /* setupParameters */
615     logFunction(printf("setupParameters\n"););
616     err_info = assign_in_sqlda(preparedStmt);
617     if (unlikely(err_info != OKAY_NO_ERROR)) {
618       preparedStmt->param_array = NULL;
619     } else if (preparedStmt->in_sqlda->sqld == 0) {
620       /* malloc(0) may return NULL, which would wrongly trigger a MEMORY_ERROR. */
621       preparedStmt->param_array = NULL;
622     } else if (unlikely(!ALLOC_TABLE(preparedStmt->param_array,
623                                      bindDataRecord,
624                                      (memSizeType) preparedStmt->in_sqlda->sqld))) {
625       err_info = MEMORY_ERROR;
626     } else {
627       memset(preparedStmt->param_array, 0,
628              (memSizeType) preparedStmt->in_sqlda->sqld * sizeof(bindDataRecord));
629     } /* if */
630     if (likely(err_info == OKAY_NO_ERROR)) {
631       numColumns = preparedStmt->in_sqlda->sqld;
632       for (column = 0, sqlvar = preparedStmt->in_sqlda->sqlvar;
633            column < numColumns; column++, sqlvar++) {
634         /* printf("sqllen: %hd\n", sqlvar->sqllen); */
635         dtype = sqlvar->sqltype & ~1; /* drop flag bit for now */
636         switch(dtype) {
637           case SQL_TEXT:
638             if (unlikely(sqlvar->sqllen <= 0)) {
639               dbInconsistent("setupParameters", "sqllen");
640               logError(printf("setupParameters: Column %d: "
641                               "sqllen %hd of SQL_TEXT is negative or zero.\n",
642                               column + 1, sqlvar->sqllen););
643               err_info = DATABASE_ERROR;
644             } else {
645               sqlvar->sqldata = (char *) malloc(sizeof(char) * (memSizeType) sqlvar->sqllen);
646             } /* if */
647             break;
648           case SQL_VARYING:
649             if (unlikely(sqlvar->sqllen <= 0)) {
650               dbInconsistent("setupParameters", "sqllen");
651               logError(printf("setupParameters: Column %d: "
652                               "sqllen %hd of SQL_VARYING is negative or zero.\n",
653                               column + 1, sqlvar->sqllen););
654               err_info = DATABASE_ERROR;
655             } else {
656               sqlvar->sqldata = (char *) malloc(sizeof(uint16Type) +
657                   sizeof(char) * (memSizeType) sqlvar->sqllen);
658             } /* if */
659             break;
660           case SQL_BOOLEAN:
661           case SQL_SHORT:
662             if (unlikely(sqlvar->sqlscale != 0)) {
663               dbInconsistent("setupParameters", "sqlscale");
664               logError(printf("setupParameters: Column %d: "
665                               "The scale of an SQL_SHORT field must be 0.\n", column););
666               err_info = DATABASE_ERROR;
667             } else {
668               sqlvar->sqldata = (char *) malloc(sizeof(short));
669             } /* if */
670             break;
671           case SQL_LONG:
672             if (unlikely(sqlvar->sqlscale != 0)) {
673               dbInconsistent("setupParameters", "sqlscale");
674               logError(printf("setupParameters: Column %d: "
675                               "The scale of an SQL_LONG field must be 0.\n", column););
676               err_info = DATABASE_ERROR;
677             } else {
678               sqlvar->sqldata = (char *) malloc(sizeof(ISC_LONG));
679             } /* if */
680             break;
681           case SQL_INT64:
682             sqlvar->sqldata = (char *) malloc(sizeof(ISC_INT64));
683             break;
684           case SQL_FLOAT:
685             sqlvar->sqldata = (char *) malloc(sizeof(float));
686             break;
687           case SQL_DOUBLE:
688             sqlvar->sqldata = (char *) malloc(sizeof(double));
689             break;
690           case SQL_BLOB:
691             sqlvar->sqldata = (char *) malloc(sizeof(ISC_QUAD));
692             break;
693           case SQL_TIMESTAMP:
694             sqlvar->sqldata = (char *) malloc(sizeof(ISC_TIMESTAMP));
695             break;
696           case SQL_TYPE_TIME:
697             sqlvar->sqldata = (char *) malloc(sizeof(ISC_TIME));
698             break;
699           case SQL_TYPE_DATE:
700             sqlvar->sqldata = (char *) malloc(sizeof(ISC_DATE));
701             break;
702           default:
703             logError(printf("setupParameters: Column %d has the unknown type %s.\n",
704                             column + 1, nameOfSqlType(dtype)););
705             err_info = RANGE_ERROR;
706             break;
707         } /* switch */
708         if (sqlvar->sqltype & 1) {
709           /* allocate variable to hold NULL status */
710           sqlvar->sqlind = (short *) malloc(sizeof(short));
711         } /* if */
712       } /* for */
713     } /* if */
714     logFunction(printf("setupParameters --> %d\n", err_info););
715     return err_info;
716   } /* setupParameters */
717 
718 
719 
setupResult(preparedStmtType preparedStmt,XSQLDA * out_sqlda)720 static errInfoType setupResult (preparedStmtType preparedStmt,
721     XSQLDA *out_sqlda)
722 
723   {
724     int column;
725     int numColumns;
726     XSQLVAR *sqlvar;
727     int dtype;
728     errInfoType err_info = OKAY_NO_ERROR;
729 
730   /* setupResult */
731     logFunction(printf("setupResult\n"););
732     err_info = assign_out_sqlda(preparedStmt, out_sqlda);
733     if (likely(err_info == OKAY_NO_ERROR)) {
734       numColumns = preparedStmt->out_sqlda->sqld;
735       for (column = 0, sqlvar = preparedStmt->out_sqlda->sqlvar;
736            column < numColumns; column++, sqlvar++) {
737         /* printf("sqllen: %hd\n", sqlvar->sqllen); */
738         dtype = sqlvar->sqltype & ~1; /* drop flag bit for now */
739         switch(dtype) {
740           case SQL_TEXT:
741             if (unlikely(sqlvar->sqllen <= 0)) {
742               dbInconsistent("setupResult", "sqllen");
743               logError(printf("setupResult: Column %d: "
744                               "sqllen %hd of SQL_TEXT is negative or zero.\n",
745                               column + 1, sqlvar->sqllen););
746               err_info = DATABASE_ERROR;
747             } else {
748               sqlvar->sqldata = (char *) malloc(sizeof(char) * (memSizeType) sqlvar->sqllen);
749             } /* if */
750             break;
751           case SQL_VARYING:
752             if (unlikely(sqlvar->sqllen <= 0)) {
753               dbInconsistent("setupResult", "sqllen");
754               logError(printf("setupResult: Column %d: "
755                               "sqllen %hd of SQL_VARYING is negative or zero.\n",
756                               column + 1, sqlvar->sqllen););
757               err_info = DATABASE_ERROR;
758             } else {
759               sqlvar->sqldata = (char *) malloc(sizeof(uint16Type) +
760                   sizeof(char) * (memSizeType) sqlvar->sqllen);
761             } /* if */
762             break;
763           case SQL_BOOLEAN:
764           case SQL_SHORT:
765             sqlvar->sqldata = (char *) malloc(sizeof(short));
766             break;
767           case SQL_LONG:
768             sqlvar->sqldata = (char *) malloc(sizeof(ISC_LONG));
769             break;
770           case SQL_INT64:
771             sqlvar->sqldata = (char *) malloc(sizeof(ISC_INT64));
772             break;
773           case SQL_FLOAT:
774             sqlvar->sqldata = (char *) malloc(sizeof(float));
775             break;
776           case SQL_DOUBLE:
777             sqlvar->sqldata = (char *) malloc(sizeof(double));
778             break;
779           case SQL_BLOB:
780             sqlvar->sqldata = (char *) malloc(sizeof(ISC_QUAD));
781             break;
782           case SQL_TIMESTAMP:
783             sqlvar->sqldata = (char *) malloc(sizeof(ISC_TIMESTAMP));
784             break;
785           case SQL_TYPE_TIME:
786             sqlvar->sqldata = (char *) malloc(sizeof(ISC_TIME));
787             break;
788           case SQL_TYPE_DATE:
789             sqlvar->sqldata = (char *) malloc(sizeof(ISC_DATE));
790             break;
791           case SQL_ARRAY:
792             sqlvar->sqldata = (char *) malloc(sizeof(ISC_QUAD));
793             break;
794           default:
795             logError(printf("setupResult: Column %d has the unknown type %s.\n",
796                             column + 1, nameOfSqlType(dtype)););
797             err_info = RANGE_ERROR;
798             break;
799         } /* switch */
800         if (sqlvar->sqltype & 1) {
801           /* allocate variable to hold NULL status */
802           sqlvar->sqlind = (short *) malloc(sizeof(short));
803         } /* if */
804       } /* for */
805     } /* if */
806     logFunction(printf("setupResult --> %d\n", err_info););
807     return err_info;
808   } /* setupResult */
809 
810 
811 
allParametersBound(preparedStmtType preparedStmt)812 static boolType allParametersBound (preparedStmtType preparedStmt)
813 
814   {
815     int column_index;
816     boolType okay = TRUE;
817 
818   /* allParametersBound */
819     for (column_index = 0; column_index < preparedStmt->in_sqlda->sqld;
820          column_index++) {
821       if (unlikely(!preparedStmt->param_array[column_index].bound)) {
822         logError(printf("sqlExecute: Unbound parameter %d.\n",
823                         column_index + 1););
824         okay = FALSE;
825       } /* if */
826     } /* for */
827     return okay;
828   } /* allParametersBound */
829 
830 
831 
intToScaledInt64(const intType value,int decimalDigits,errInfoType * err_info)832 static int64Type intToScaledInt64 (const intType value,
833     int decimalDigits, errInfoType *err_info)
834 
835   {
836     int64Type factor;
837 
838   /* intToScaledInt64 */
839     logFunction(printf("intToScaledInt64(" FMT_D ", %d, *)\n",
840                        value, decimalDigits););
841     switch (decimalDigits) {
842       case  0: factor =                   1; break;
843       case  1: factor =                  10; break;
844       case  2: factor =                 100; break;
845       case  3: factor =                1000; break;
846       case  4: factor =               10000; break;
847       case  5: factor =              100000; break;
848       case  6: factor =             1000000; break;
849       case  7: factor =            10000000; break;
850       case  8: factor =           100000000; break;
851       case  9: factor =          1000000000; break;
852       case 10: factor =         10000000000; break;
853       case 11: factor =        100000000000; break;
854       case 12: factor =       1000000000000; break;
855       case 13: factor =      10000000000000; break;
856       case 14: factor =     100000000000000; break;
857       case 15: factor =    1000000000000000; break;
858       case 16: factor =   10000000000000000; break;
859       case 17: factor =  100000000000000000; break;
860       case 18: factor = 1000000000000000000; break;
861       default:
862         logError(printf("intToScaledInt64: Wrong number of decimal digits: %d\n",
863                         decimalDigits););
864         raise_error(RANGE_ERROR);
865         factor = 1;
866         break;
867     } /* switch */
868     if (value < 0) {
869       if (unlikely(value < INT64TYPE_MIN / factor)) {
870         logError(printf("intToScaledInt64: Value (" FMT_D
871                         ") smaller than minimum (" FMT_D ").\n",
872                         value, INT64TYPE_MIN / factor));
873         *err_info = RANGE_ERROR;
874         factor = 1;
875       } /* if */
876     } else {
877       if (unlikely(value > INT64TYPE_MAX / factor)) {
878         logError(printf("intToScaledInt64: Value (" FMT_D
879                         ") larger than maximum (" FMT_D ").\n",
880                         value, INT64TYPE_MAX / factor));
881         *err_info = RANGE_ERROR;
882         factor = 1;
883       } /* if */
884     } /* if */
885     return value * factor;
886   } /* intToScaledInt64 */
887 
888 
889 
bigIntToScaledInt64(const const_bigIntType value,int decimalDigits,errInfoType * err_info)890 static int64Type bigIntToScaledInt64 (const const_bigIntType value,
891     int decimalDigits, errInfoType *err_info)
892 
893   {
894     bigIntType number;
895     int64Type int64Value = 0;
896 
897   /* bigIntToScaledInt64 */
898     logFunction(printf("bigIntToScaledInt64(%s, %d, *)\n",
899                        bigHexCStri(value), decimalDigits););
900     number = bigIPowSignedDigit(10, decimalDigits);
901     if (number != NULL) {
902       bigMultAssign(&number, value);
903       if (number != NULL) {
904         /* printf("mantissaValue: ");
905            prot_bigint(mantissaValue);
906            printf("\n"); */
907         int64Value = bigToInt64(number, err_info);
908         bigDestr(number);
909       } /* if */
910     } /* if */
911     return int64Value;
912   } /* bigIntToScaledInt64 */
913 
914 
915 
bigRatToScaledInt64(const const_bigIntType numerator,const const_bigIntType denominator,int decimalDigits,errInfoType * err_info)916 static int64Type bigRatToScaledInt64 (const const_bigIntType numerator,
917     const const_bigIntType denominator, int decimalDigits,
918     errInfoType *err_info)
919 
920   {
921     bigIntType number;
922     bigIntType mantissaValue;
923     int64Type int64Value = 0;
924 
925   /* bigRatToScaledInt64 */
926     logFunction(printf("bigRatToScaledInt64(%s, %s, %d, *)\n",
927                        bigHexCStri(numerator), bigHexCStri(denominator),
928                        decimalDigits););
929     if (unlikely(bigEqSignedDigit(denominator, 0))) {
930       /* Numeric values do not support Infinity and NaN. */
931       logError(printf("bigRatToScaledInt64: Decimal values do not support Infinity and NaN.\n"););
932       *err_info = RANGE_ERROR;
933     } else {
934       number = bigIPowSignedDigit(10, decimalDigits);
935       if (number != NULL) {
936         bigMultAssign(&number, numerator);
937         mantissaValue = bigDiv(number, denominator);
938         bigDestr(number);
939         if (mantissaValue != NULL) {
940           /* printf("mantissaValue: ");
941              prot_bigint(mantissaValue);
942              printf("\n"); */
943           int64Value = bigToInt64(mantissaValue, err_info);
944           bigDestr(mantissaValue);
945         } /* if */
946       } /* if */
947     } /* if */
948     return int64Value;
949   } /* bigRatToScaledInt64 */
950 
951 
952 
getBlobLength(isc_blob_handle blob_handle,errInfoType * err_info)953 static memSizeType getBlobLength (isc_blob_handle blob_handle, errInfoType *err_info)
954 
955   {
956     ISC_STATUS status_vector[20];
957     char blob_items[] = {isc_info_blob_total_length};
958     char res_buffer[20];
959     char *ptr;
960     char item;
961     short length;
962     boolType totalLengthAssigned = FALSE;
963     ISC_INT64 totalLength;
964 
965   /* getBlobLength */
966     logFunction(printf("getBlobLength(" FMT_U32 ", *)\n", blob_handle););
967     if ((isc_blob_info(status_vector,
968                        &blob_handle,
969                        sizeof(blob_items),
970                        blob_items,
971                        sizeof(res_buffer),
972                        res_buffer),
973                status_vector[0] == 1 && status_vector[1] != 0)) {
974       setDbErrorMsg("getBlobLength", "isc_blob_info",
975                     status_vector);
976       logError(printf("getBlobLength: isc_blob_info() error:\n%s\n",
977                       dbError.message););
978       *err_info = DATABASE_ERROR;
979       totalLength = 0;
980     } else {
981       for (ptr = res_buffer; *ptr != isc_info_end;) {
982         item = *ptr++;
983         length = (short) isc_portable_integer(ptr, 2);
984         ptr += 2;
985         switch (item) {
986           case isc_info_blob_total_length:
987             totalLength = isc_portable_integer(ptr, length);
988             totalLengthAssigned = TRUE;
989             break;
990           case isc_info_truncated:
991             /* handle error */
992             break;
993           default:
994             break;
995         } /* switch */
996         ptr += length;
997       } /* for */
998     } /* if */
999     if (unlikely(!totalLengthAssigned)) {
1000       dbInconsistent("getBlobLength", "isc_blob_info");
1001       logError(printf("getBlobLength: Isc_blob_info returns no value "
1002                       " for isc_info_blob_total_length.\n"););
1003       *err_info = DATABASE_ERROR;
1004       totalLength = 0;
1005     } else if (unlikely(totalLength < 0)) {
1006       dbInconsistent("getBlobLength", "isc_blob_info");
1007       logError(printf("getBlobLength: Isc_blob_info returns negative "
1008                       " value for isc_info_blob_total_length: " FMT_D64 ".\n",
1009                       (int64Type) totalLength););
1010       *err_info = DATABASE_ERROR;
1011       totalLength = 0;
1012     } if (unlikely(totalLength > MAX_MEMSIZETYPE)) {
1013       /* It is not possible to cast totalLength to memSizeType. */
1014       /* Memory with this length cannot be allocated. */
1015       *err_info = MEMORY_ERROR;
1016       totalLength = 0;
1017     } /* if */
1018     logFunction(printf("getBlobLength --> " FMT_U_MEM "\n",
1019                        (memSizeType) totalLength););
1020     return (memSizeType) totalLength;
1021   } /* getBlobLength */
1022 
1023 
1024 
copyBlobContents(isc_blob_handle blob_handle,memSizeType blobLength,ustriType destination)1025 static memSizeType copyBlobContents (isc_blob_handle blob_handle,
1026     memSizeType blobLength, ustriType destination)
1027 
1028   {
1029     memSizeType bytesToGet;
1030     unsigned short segmentLength;
1031     unsigned short actualSegmentLength;
1032     ISC_STATUS status_vector[20];
1033     ISC_STATUS blob_stat;
1034 
1035   /* copyBlobContents */
1036     bytesToGet = blobLength;
1037     if (bytesToGet > UINT16TYPE_MAX) {
1038       segmentLength = UINT16TYPE_MAX;
1039     } else {
1040       segmentLength = (unsigned short) bytesToGet;
1041     } /* if */
1042     blob_stat = isc_get_segment(status_vector,
1043                                 &blob_handle,
1044                                 &actualSegmentLength,
1045                                 segmentLength,
1046                                 (char *) destination);
1047     while (blob_stat == 0 || status_vector[1] == isc_segment) {
1048       /* isc_get_segment returns 0 if a segment was successfully read. */
1049       /* status_vector[1] is set to isc_segment if only part of a */
1050       /* segment was read due to the buffer (blob_segment) not being */
1051       /* large enough. In that case, the following calls to */
1052       /* isc_get_segment() read the rest of the buffer. */
1053       bytesToGet -= (memSizeType) actualSegmentLength;
1054       destination += actualSegmentLength;
1055       if (bytesToGet > UINT16TYPE_MAX) {
1056         segmentLength = UINT16TYPE_MAX;
1057       } else {
1058         segmentLength = (unsigned short) bytesToGet;
1059       } /* if */
1060       blob_stat = isc_get_segment(status_vector,
1061                                   &blob_handle,
1062                                   &actualSegmentLength,
1063                                   segmentLength,
1064                                   (char *) destination);
1065     } /* while */
1066     return blobLength - bytesToGet;
1067   } /* copyBlobContents */
1068 
1069 
1070 
getBlob(preparedStmtType preparedStmt,ISC_QUAD * blob_id,errInfoType * err_info)1071 static bstriType getBlob (preparedStmtType preparedStmt,
1072     ISC_QUAD *blob_id, errInfoType *err_info)
1073 
1074   {
1075     ISC_STATUS status_vector[20];
1076     isc_blob_handle blob_handle = 0;
1077     memSizeType blobLength;
1078     bstriType bstri;
1079 
1080   /* getBlob */
1081     logFunction(printf("getBlob(" FMT_U_MEM ", " FMT_X64 ", *)\n",
1082                        (memSizeType) preparedStmt, *(uint64Type *) blob_id););
1083     /* Blob_handle must be zero when isc_open_blob2 is called. */
1084     if ((isc_open_blob2(status_vector,
1085                         &preparedStmt->db->connection,
1086                         &preparedStmt->db->trans_handle,
1087                         &blob_handle,
1088                         blob_id,
1089                         0,
1090                         NULL),
1091         status_vector[0] == 1 && status_vector[1] != 0)) {
1092       setDbErrorMsg("getBlob", "isc_open_blob2",
1093                     status_vector);
1094       logError(printf("getBlob: isc_open_blob2() error:\n%s\n",
1095                       dbError.message););
1096       *err_info = DATABASE_ERROR;
1097       bstri = NULL;
1098     } else {
1099       blobLength = getBlobLength(blob_handle, err_info);
1100       if (likely(*err_info == OKAY_NO_ERROR)) {
1101         if (unlikely(blobLength > MAX_BSTRI_LEN ||
1102                      !ALLOC_BSTRI_SIZE_OK(bstri, blobLength))) {
1103           *err_info = MEMORY_ERROR;
1104           bstri = NULL;
1105         } else {
1106           bstri->size = copyBlobContents(blob_handle, blobLength, bstri->mem);
1107         } /* if */
1108       } else {
1109         bstri = NULL;
1110       } /* if */
1111       isc_close_blob(status_vector, &blob_handle);
1112       if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
1113         setDbErrorMsg("getBlob", "isc_close_blob",
1114                       status_vector);
1115         logError(printf("getBlob: isc_close_blob() error:\n%s\n",
1116                         dbError.message););
1117         *err_info = DATABASE_ERROR;
1118         FREE_BSTRI(bstri, blobLength);
1119         bstri = NULL;
1120       } /* if */
1121     } /* if */
1122     logFunction(printf("getBlob --> \"%s\"\n",
1123                         bstriAsUnquotedCStri(bstri)););
1124     return bstri;
1125   } /* getBlob */
1126 
1127 
1128 
getBlobAsStri(preparedStmtType preparedStmt,ISC_QUAD * blob_id,errInfoType * err_info)1129 static striType getBlobAsStri (preparedStmtType preparedStmt,
1130     ISC_QUAD *blob_id, errInfoType *err_info)
1131 
1132   {
1133     ISC_STATUS status_vector[20];
1134     isc_blob_handle blob_handle = 0;
1135     memSizeType blobLength;
1136     memSizeType actualBlobLength;
1137     striType stri;
1138 
1139   /* getBlobAsStri */
1140     logFunction(printf("getBlobAsStri(" FMT_U_MEM ", " FMT_X64 ", *)\n",
1141                        (memSizeType) preparedStmt, *(uint64Type *) blob_id););
1142     /* Blob_handle must be zero when isc_open_blob2 is called. */
1143     if (unlikely((isc_open_blob2(status_vector,
1144                                  &preparedStmt->db->connection,
1145                                  &preparedStmt->db->trans_handle,
1146                                  &blob_handle,
1147                                  blob_id,
1148                                  0,
1149                                  NULL),
1150                   status_vector[0] == 1 && status_vector[1] != 0))) {
1151       setDbErrorMsg("getBlobAsStri", "isc_open_blob2",
1152                     status_vector);
1153       logError(printf("getBlobAsStri: isc_open_blob2() error:\n%s\n",
1154                       dbError.message););
1155       *err_info = DATABASE_ERROR;
1156       stri = NULL;
1157     } else {
1158       blobLength = getBlobLength(blob_handle, err_info);
1159       if (likely(*err_info == OKAY_NO_ERROR)) {
1160         if (unlikely(blobLength > MAX_STRI_LEN ||
1161                      !ALLOC_STRI_SIZE_OK(stri, blobLength))) {
1162           *err_info = MEMORY_ERROR;
1163           stri = NULL;
1164         } else {
1165           actualBlobLength = copyBlobContents(blob_handle, blobLength, (ustriType) stri->mem);
1166           memcpy_to_strelem(stri->mem, (ustriType) stri->mem, actualBlobLength);
1167           stri->size = actualBlobLength;
1168         } /* if */
1169       } else {
1170         stri = NULL;
1171       } /* if */
1172       isc_close_blob(status_vector, &blob_handle);
1173       if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
1174         setDbErrorMsg("getBlobAsStri", "isc_close_blob",
1175                       status_vector);
1176         logError(printf("getBlobAsStri: isc_close_blob() error:\n%s\n",
1177                         dbError.message););
1178         *err_info = DATABASE_ERROR;
1179         FREE_STRI(stri, blobLength);
1180         stri = NULL;
1181       } /* if */
1182     } /* if */
1183     logFunction(printf("getBlobAsStri --> \"%s\"\n",
1184                        striAsUnquotedCStri(stri)););
1185     return stri;
1186   } /* getBlobAsStri */
1187 
1188 
1189 
getClob(preparedStmtType preparedStmt,ISC_QUAD * blob_id,errInfoType * err_info)1190 static striType getClob (preparedStmtType preparedStmt,
1191     ISC_QUAD *blob_id, errInfoType *err_info)
1192 
1193   {
1194     ISC_STATUS status_vector[20];
1195     isc_blob_handle blob_handle = 0;
1196     memSizeType blobLength;
1197     memSizeType actualBlobLength;
1198     cstriType utf8_stri;
1199     striType stri;
1200 
1201   /* getClob */
1202     logFunction(printf("getClob(" FMT_U_MEM ", " FMT_X64 ", *)\n",
1203                        (memSizeType) preparedStmt, *(uint64Type *) blob_id););
1204     /* Blob_handle must be zero when isc_open_blob2 is called. */
1205     if (unlikely((isc_open_blob2(status_vector,
1206                                  &preparedStmt->db->connection,
1207                                  &preparedStmt->db->trans_handle,
1208                                  &blob_handle,
1209                                  blob_id,
1210                                  0,
1211                                  NULL),
1212                   status_vector[0] == 1 && status_vector[1] != 0))) {
1213       setDbErrorMsg("getClob", "isc_open_blob2",
1214                     status_vector);
1215       logError(printf("getClob: isc_open_blob2() error:\n%s\n",
1216                       dbError.message););
1217       *err_info = DATABASE_ERROR;
1218       stri = NULL;
1219     } else {
1220       blobLength = getBlobLength(blob_handle, err_info);
1221       if (likely(*err_info == OKAY_NO_ERROR)) {
1222         if (unlikely(blobLength > MAX_MEMSIZETYPE ||
1223                      !ALLOC_BYTES(utf8_stri, blobLength))) {
1224           *err_info = MEMORY_ERROR;
1225           stri = NULL;
1226         } else {
1227           actualBlobLength = copyBlobContents(blob_handle, blobLength, (ustriType) utf8_stri);
1228           stri = cstri8_buf_to_stri(utf8_stri, actualBlobLength, err_info);
1229           FREE_BYTES(utf8_stri, blobLength);
1230         } /* if */
1231       } else {
1232         stri = NULL;
1233       } /* if */
1234       isc_close_blob(status_vector, &blob_handle);
1235       if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
1236         setDbErrorMsg("getClob", "isc_close_blob",
1237                       status_vector);
1238         logError(printf("getClob: isc_close_blob() error:\n%s\n",
1239                         dbError.message););
1240         *err_info = DATABASE_ERROR;
1241         FREE_STRI(stri, blobLength);
1242         stri = NULL;
1243       } /* if */
1244     } /* if */
1245     logFunction(printf("getClob --> \"%s\"\n",
1246                        striAsUnquotedCStri(stri)););
1247     return stri;
1248   } /* getClob */
1249 
1250 
1251 
putBlob(preparedStmtType preparedStmt,const const_bstriType bstri,XSQLVAR * sqlvar)1252 static errInfoType putBlob (preparedStmtType preparedStmt,
1253     const const_bstriType bstri, XSQLVAR *sqlvar)
1254 
1255   {
1256     ISC_STATUS status_vector[20];
1257     isc_blob_handle blob_handle = 0;
1258     ISC_QUAD blob_id;
1259     memSizeType byteIndex;
1260     memSizeType bytesToWrite;
1261     unsigned short segmentLength;
1262     errInfoType err_info = OKAY_NO_ERROR;
1263 
1264   /* putBlob */
1265     logFunction(printf("putBlob(" FMT_U_MEM ", \"%s\")\n",
1266                        (memSizeType) preparedStmt, bstriAsUnquotedCStri(bstri)));
1267     /* Blob_handle must be zero when isc_create_blob2() is called. */
1268     if (unlikely((isc_create_blob2(status_vector,
1269                                   &preparedStmt->db->connection,
1270                                   &preparedStmt->db->trans_handle,
1271                                   &blob_handle,
1272                                   &blob_id,
1273                                   0,
1274                                   NULL),
1275                   status_vector[0] == 1 && status_vector[1] != 0))) {
1276       setDbErrorMsg("putBlob", "isc_create_blob2",
1277                     status_vector);
1278       logError(printf("putBlob: isc_create_blob2() error:\n%s\n",
1279                       dbError.message););
1280       err_info = DATABASE_ERROR;
1281     } else {
1282       byteIndex = 0;
1283       bytesToWrite = bstri->size;
1284       while (bytesToWrite > 0 && err_info == OKAY_NO_ERROR) {
1285         if (bytesToWrite > UINT16TYPE_MAX) {
1286           segmentLength = UINT16TYPE_MAX;
1287         } else {
1288           segmentLength = (unsigned short) bytesToWrite;
1289         } /* if */
1290         if (unlikely((isc_put_segment(status_vector,
1291                                       &blob_handle,
1292                                       segmentLength,
1293                                       (char *) &bstri->mem[byteIndex]),
1294                       status_vector[0] == 1 && status_vector[1] != 0))) {
1295           setDbErrorMsg("putBlob", "isc_put_segment",
1296                         status_vector);
1297           logError(printf("putBlob: isc_put_segment() error:\n%s\n",
1298                           dbError.message););
1299           err_info = DATABASE_ERROR;
1300         } else {
1301           byteIndex += segmentLength;
1302           bytesToWrite -= segmentLength;
1303         } /* if */
1304       } /* while */
1305       if (unlikely((isc_close_blob(status_vector,
1306                                    &blob_handle),
1307                     status_vector[0] == 1 && status_vector[1] != 0))) {
1308         setDbErrorMsg("getBlob", "isc_close_blob",
1309                       status_vector);
1310         logError(printf("getBlob: isc_close_blob() error:\n%s\n",
1311                         dbError.message););
1312         err_info = DATABASE_ERROR;
1313       } else if (likely(err_info == OKAY_NO_ERROR)) {
1314         memcpy(sqlvar->sqldata, &blob_id, sizeof(ISC_QUAD));
1315       } /* if */
1316     } /* if */
1317     logFunction(printf("putBlob --> %d\n", err_info););
1318     return err_info;
1319   } /* putBlob */
1320 
1321 
1322 
sqlBindBigInt(sqlStmtType sqlStatement,intType pos,const const_bigIntType value)1323 static void sqlBindBigInt (sqlStmtType sqlStatement, intType pos,
1324     const const_bigIntType value)
1325 
1326   {
1327     preparedStmtType preparedStmt;
1328     ISC_STATUS status_vector[20];
1329     XSQLVAR *sqlvar;
1330     striType decimalNumber;
1331     errInfoType err_info = OKAY_NO_ERROR;
1332 
1333   /* sqlBindBigInt */
1334     logFunction(printf("sqlBindBigInt(" FMT_U_MEM ", " FMT_D ", %s)\n",
1335                        (memSizeType) sqlStatement, pos, bigHexCStri(value)););
1336     preparedStmt = (preparedStmtType) sqlStatement;
1337     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
1338       logError(printf("sqlBindBigInt: pos: " FMT_D ", max pos: %hd.\n",
1339                       pos, preparedStmt->in_sqlda->sqld););
1340       raise_error(RANGE_ERROR);
1341     } else {
1342       if (preparedStmt->executeSuccessful) {
1343         if (unlikely((isc_dsql_free_statement(status_vector,
1344                                               &preparedStmt->ppStmt,
1345                                               DSQL_close),
1346                       status_vector[0] == 1 && status_vector[1] != 0))) {
1347           setDbErrorMsg("sqlBindBigInt", "isc_dsql_free_statement",
1348                         status_vector);
1349           logError(printf("sqlBindBigInt: isc_dsql_free_statement error:\n%s\n",
1350                           dbError.message););
1351           err_info = DATABASE_ERROR;
1352         } else {
1353           preparedStmt->executeSuccessful = FALSE;
1354         } /* if */
1355       } /* if */
1356       if (likely(err_info == OKAY_NO_ERROR)) {
1357         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
1358         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
1359         switch (sqlvar->sqltype & ~1) {
1360           case SQL_SHORT:
1361             *(int16Type *) sqlvar->sqldata = bigToInt16(value, &err_info);
1362             break;
1363           case SQL_LONG:
1364             *(int32Type *) sqlvar->sqldata = bigToInt32(value, &err_info);
1365             break;
1366           case SQL_INT64:
1367             /* printf("sqlBindBigInt: scale: %hd\n", sqlvar->sqlscale); */
1368             if (sqlvar->sqlscale == 0) {
1369               *(int64Type *) sqlvar->sqldata = bigToInt64(value, &err_info);
1370             } else {
1371               *(int64Type *) sqlvar->sqldata = bigIntToScaledInt64(value,
1372                   -sqlvar->sqlscale, &err_info);
1373             } /* if */
1374             break;
1375           case SQL_FLOAT:
1376             *(float *) sqlvar->sqldata = (float) bigIntToDouble(value);
1377             break;
1378           case SQL_DOUBLE:
1379             *(double *) sqlvar->sqldata = bigIntToDouble(value);
1380             break;
1381           case SQL_TEXT:
1382             decimalNumber = bigStr(value);
1383             if (decimalNumber == NULL) {
1384               err_info = MEMORY_ERROR;
1385             } else {
1386               /* setupParameters() has already checked that sqllen > 0 holds */
1387               if (unlikely((memSizeType) sqlvar->sqllen < decimalNumber->size)) {
1388                 logError(printf("sqlBindBigInt: Parameter " FMT_D ": "
1389                                 "Decimal representation of %s longer than allowed (%hd).\n",
1390                                 pos, striAsUnquotedCStri(decimalNumber),
1391                                 sqlvar->sqllen););
1392                 err_info = RANGE_ERROR;
1393               } else {
1394                 memcpy_from_strelem((ustriType) sqlvar->sqldata,
1395                     decimalNumber->mem, decimalNumber->size);
1396                 memset(&sqlvar->sqldata[decimalNumber->size], ' ',
1397                     (memSizeType) sqlvar->sqllen - decimalNumber->size);
1398               } /* if */
1399               FREE_STRI(decimalNumber, decimalNumber->size);
1400             } /* if */
1401             break;
1402           case SQL_VARYING:
1403             decimalNumber = bigStr(value);
1404             if (decimalNumber == NULL) {
1405               err_info = MEMORY_ERROR;
1406             } else {
1407               /* setupParameters() has already checked that sqllen > 0 holds */
1408               if (unlikely((memSizeType) sqlvar->sqllen < decimalNumber->size)) {
1409                 logError(printf("sqlBindBigInt: Parameter " FMT_D ": "
1410                                 "Decimal representation of %s longer than allowed (%hd).\n",
1411                                 pos, striAsUnquotedCStri(decimalNumber),
1412                                 sqlvar->sqllen););
1413                 err_info = RANGE_ERROR;
1414               } else {
1415                 *(int16Type *) sqlvar->sqldata =
1416                     (int16Type) decimalNumber->size;
1417                 memcpy_from_strelem((ustriType)
1418                     &sqlvar->sqldata[sizeof(uint16Type)],
1419                     decimalNumber->mem, decimalNumber->size);
1420                 memset(&sqlvar->sqldata[sizeof(uint16Type) + decimalNumber->size],
1421                     '\0', (memSizeType) sqlvar->sqllen - decimalNumber->size);
1422               } /* if */
1423               FREE_STRI(decimalNumber, decimalNumber->size);
1424             } /* if */
1425             break;
1426           default:
1427             logError(printf("sqlBindBigInt: Parameter " FMT_D " has the unknown type %s.\n",
1428                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
1429             err_info = RANGE_ERROR;
1430             break;
1431         } /* switch */
1432         if (likely(err_info == OKAY_NO_ERROR)) {
1433           if (sqlvar->sqltype & 1) {
1434             *sqlvar->sqlind = 0;
1435           } /* if */
1436           preparedStmt->fetchOkay = FALSE;
1437           preparedStmt->param_array[pos - 1].bound = TRUE;
1438         } /* if */
1439       } /* if */
1440       if (unlikely(err_info != OKAY_NO_ERROR)) {
1441         raise_error(err_info);
1442       } /* if */
1443     } /* if */
1444   } /* sqlBindBigInt */
1445 
1446 
1447 
sqlBindBigRat(sqlStmtType sqlStatement,intType pos,const const_bigIntType numerator,const const_bigIntType denominator)1448 static void sqlBindBigRat (sqlStmtType sqlStatement, intType pos,
1449     const const_bigIntType numerator, const const_bigIntType denominator)
1450 
1451   {
1452     preparedStmtType preparedStmt;
1453     ISC_STATUS status_vector[20];
1454     XSQLVAR *sqlvar;
1455     errInfoType err_info = OKAY_NO_ERROR;
1456 
1457   /* sqlBindBigRat */
1458     logFunction(printf("sqlBindBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s)\n",
1459                        (memSizeType) sqlStatement, pos,
1460                        bigHexCStri(numerator), bigHexCStri(denominator)););
1461     preparedStmt = (preparedStmtType) sqlStatement;
1462     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
1463       logError(printf("sqlBindBigRat: pos: " FMT_D ", max pos: %hd.\n",
1464                       pos, preparedStmt->in_sqlda->sqld););
1465       raise_error(RANGE_ERROR);
1466     } else {
1467       if (preparedStmt->executeSuccessful) {
1468         if (unlikely((isc_dsql_free_statement(status_vector,
1469                                               &preparedStmt->ppStmt,
1470                                               DSQL_close),
1471                       status_vector[0] == 1 && status_vector[1] != 0))) {
1472           setDbErrorMsg("sqlBindBigRat", "isc_dsql_free_statement",
1473                         status_vector);
1474           logError(printf("sqlBindBigRat: isc_dsql_free_statement error:\n%s\n",
1475                           dbError.message););
1476           err_info = DATABASE_ERROR;
1477         } else {
1478           preparedStmt->executeSuccessful = FALSE;
1479         } /* if */
1480       } /* if */
1481       if (likely(err_info == OKAY_NO_ERROR)) {
1482         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
1483         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
1484         switch (sqlvar->sqltype & ~1) {
1485           case SQL_INT64:
1486             /* printf("sqlBindBigRat: scale: %hd\n", sqlvar->sqlscale); */
1487             *(int64Type *) sqlvar->sqldata = bigRatToScaledInt64(numerator, denominator,
1488                 -sqlvar->sqlscale, &err_info);
1489             break;
1490           case SQL_FLOAT:
1491             *(float *) sqlvar->sqldata =
1492                 (float) bigRatToDouble(numerator, denominator);;
1493             break;
1494           case SQL_DOUBLE:
1495             *(double *) sqlvar->sqldata =
1496                 bigRatToDouble(numerator, denominator);
1497             break;
1498           default:
1499             logError(printf("sqlBindBigRat: Parameter " FMT_D " has the unknown type %s.\n",
1500                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
1501             err_info = RANGE_ERROR;
1502             break;
1503         } /* switch */
1504         if (likely(err_info == OKAY_NO_ERROR)) {
1505           if (sqlvar->sqltype & 1) {
1506             *sqlvar->sqlind = 0;
1507           } /* if */
1508           preparedStmt->fetchOkay = FALSE;
1509           preparedStmt->param_array[pos - 1].bound = TRUE;
1510         } /* if */
1511       } /* if */
1512       if (unlikely(err_info != OKAY_NO_ERROR)) {
1513         raise_error(err_info);
1514       } /* if */
1515     } /* if */
1516   } /* sqlBindBigRat */
1517 
1518 
1519 
sqlBindBool(sqlStmtType sqlStatement,intType pos,boolType value)1520 static void sqlBindBool (sqlStmtType sqlStatement, intType pos, boolType value)
1521 
1522   {
1523     preparedStmtType preparedStmt;
1524     ISC_STATUS status_vector[20];
1525     XSQLVAR *sqlvar;
1526     errInfoType err_info = OKAY_NO_ERROR;
1527 
1528   /* sqlBindBool */
1529     logFunction(printf("sqlBindBool(" FMT_U_MEM ", " FMT_D ", %s)\n",
1530                        (memSizeType) sqlStatement, pos, value ? "TRUE" : "FALSE"););
1531     preparedStmt = (preparedStmtType) sqlStatement;
1532     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
1533       logError(printf("sqlBindBool: pos: " FMT_D ", max pos: %hd.\n",
1534                       pos, preparedStmt->in_sqlda->sqld););
1535       raise_error(RANGE_ERROR);
1536     } else {
1537       if (preparedStmt->executeSuccessful) {
1538         if (unlikely((isc_dsql_free_statement(status_vector,
1539                                               &preparedStmt->ppStmt,
1540                                               DSQL_close),
1541                       status_vector[0] == 1 && status_vector[1] != 0))) {
1542           setDbErrorMsg("sqlBindBool", "isc_dsql_free_statement",
1543                         status_vector);
1544           logError(printf("sqlBindBool: isc_dsql_free_statement error:\n%s\n",
1545                           dbError.message););
1546           err_info = DATABASE_ERROR;
1547         } else {
1548           preparedStmt->executeSuccessful = FALSE;
1549         } /* if */
1550       } /* if */
1551       if (likely(err_info == OKAY_NO_ERROR)) {
1552         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
1553         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
1554         switch (sqlvar->sqltype & ~1) {
1555           case SQL_BOOLEAN:
1556           case SQL_SHORT:
1557             *(int16Type *) sqlvar->sqldata = (int16Type) value;
1558             break;
1559           case SQL_LONG:
1560             *(int32Type *) sqlvar->sqldata = (int32Type) value;
1561             break;
1562           case SQL_INT64:
1563             /* printf("sqlBindBool: scale: %hd\n", sqlvar->sqlscale); */
1564             if (unlikely(sqlvar->sqlscale != 0)) {
1565               logError(printf("sqlBindBool: Parameter " FMT_D ": "
1566                               "The scale of a boolean field must be 0.\n", pos););
1567               err_info = RANGE_ERROR;
1568             } else {
1569               *(int64Type *) sqlvar->sqldata = (int64Type) value;
1570             } /* if */
1571             break;
1572           case SQL_TEXT:
1573             if (unlikely(sqlvar->sqllen != 1)) {
1574               logError(printf("sqlBindBool: Parameter " FMT_D ": "
1575                               "The size of a boolean field must be 1.\n", pos););
1576               err_info = RANGE_ERROR;
1577             } else {
1578               ((char *) sqlvar->sqldata)[0] = (char) ('0' + value);
1579             } /* if */
1580            break;
1581           default:
1582             logError(printf("sqlBindBool: Parameter " FMT_D " has the unknown type %s.\n",
1583                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
1584             err_info = RANGE_ERROR;
1585             break;
1586         } /* switch */
1587         if (likely(err_info == OKAY_NO_ERROR)) {
1588           if (sqlvar->sqltype & 1) {
1589             *sqlvar->sqlind = 0;
1590           } /* if */
1591           preparedStmt->fetchOkay = FALSE;
1592           preparedStmt->param_array[pos - 1].bound = TRUE;
1593         } /* if */
1594       } /* if */
1595       if (unlikely(err_info != OKAY_NO_ERROR)) {
1596         raise_error(err_info);
1597       } /* if */
1598     } /* if */
1599   } /* sqlBindBool */
1600 
1601 
1602 
sqlBindBStri(sqlStmtType sqlStatement,intType pos,const const_bstriType bstri)1603 static void sqlBindBStri (sqlStmtType sqlStatement, intType pos,
1604     const const_bstriType bstri)
1605 
1606   {
1607     preparedStmtType preparedStmt;
1608     ISC_STATUS status_vector[20];
1609     XSQLVAR *sqlvar;
1610     errInfoType err_info = OKAY_NO_ERROR;
1611 
1612   /* sqlBindBStri */
1613     logFunction(printf("sqlBindBStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
1614                        (memSizeType) sqlStatement, pos, bstriAsUnquotedCStri(bstri)););
1615     preparedStmt = (preparedStmtType) sqlStatement;
1616     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
1617       logError(printf("sqlBindBStri: pos: " FMT_D ", max pos: %hd.\n",
1618                       pos, preparedStmt->in_sqlda->sqld););
1619       raise_error(RANGE_ERROR);
1620     } else {
1621       if (preparedStmt->executeSuccessful) {
1622         if (unlikely((isc_dsql_free_statement(status_vector,
1623                                               &preparedStmt->ppStmt,
1624                                               DSQL_close),
1625                       status_vector[0] == 1 && status_vector[1] != 0))) {
1626           setDbErrorMsg("sqlBindBStri", "isc_dsql_free_statement",
1627                         status_vector);
1628           logError(printf("sqlBindBStri: isc_dsql_free_statement error:\n%s\n",
1629                           dbError.message););
1630           err_info = DATABASE_ERROR;
1631         } else {
1632           preparedStmt->executeSuccessful = FALSE;
1633         } /* if */
1634       } /* if */
1635       if (likely(err_info == OKAY_NO_ERROR)) {
1636         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
1637         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
1638         switch (sqlvar->sqltype & ~1) {
1639           case SQL_BLOB:
1640             err_info = putBlob(preparedStmt, bstri, sqlvar);
1641             break;
1642           case SQL_TEXT:
1643             /* setupParameters() has already checked that sqllen > 0 holds */
1644             if (unlikely((memSizeType) sqlvar->sqllen < bstri->size)) {
1645               logError(printf("sqlBindBStri(*, " FMT_D ", \"%s\"): "
1646                               "Bstring longer than allowed (%hd).\n",
1647                               pos, bstriAsUnquotedCStri(bstri),
1648                               sqlvar->sqllen););
1649               err_info = RANGE_ERROR;
1650             } else {
1651               memcpy(sqlvar->sqldata, bstri->mem, bstri->size);
1652               memset(&sqlvar->sqldata[bstri->size], ' ',
1653                      (memSizeType) sqlvar->sqllen - bstri->size);
1654             } /* if */
1655             break;
1656           case SQL_VARYING:
1657             /* setupParameters() has already checked that sqllen > 0 holds */
1658             if (unlikely((memSizeType) sqlvar->sqllen < bstri->size)) {
1659               logError(printf("sqlBindBStri(*, " FMT_D ", \"%s\"): "
1660                               "Bstring longer than allowed (%hd).\n",
1661                               pos, bstriAsUnquotedCStri(bstri),
1662                               sqlvar->sqllen););
1663               err_info = RANGE_ERROR;
1664             } else {
1665               *(int16Type *) sqlvar->sqldata = (int16Type) bstri->size;
1666               memcpy(&sqlvar->sqldata[sizeof(uint16Type)],
1667                      bstri->mem, bstri->size);
1668               memset(&sqlvar->sqldata[sizeof(uint16Type) + bstri->size],
1669                      '\0', (memSizeType) sqlvar->sqllen - bstri->size);
1670             } /* if */
1671             break;
1672           default:
1673             logError(printf("sqlBindBStri: Parameter " FMT_D " has the unknown type %s.\n",
1674                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
1675             err_info = RANGE_ERROR;
1676             break;
1677         } /* switch */
1678         if (likely(err_info == OKAY_NO_ERROR)) {
1679           if (sqlvar->sqltype & 1) {
1680             *sqlvar->sqlind = 0;
1681           } /* if */
1682           preparedStmt->fetchOkay = FALSE;
1683           preparedStmt->param_array[pos - 1].bound = TRUE;
1684         } /* if */
1685       } /* if */
1686       if (unlikely(err_info != OKAY_NO_ERROR)) {
1687         raise_error(err_info);
1688       } /* if */
1689     } /* if */
1690   } /* sqlBindBStri */
1691 
1692 
1693 
sqlBindDuration(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second)1694 static void sqlBindDuration (sqlStmtType sqlStatement, intType pos,
1695     intType year, intType month, intType day, intType hour,
1696     intType minute, intType second, intType micro_second)
1697 
1698   {
1699     preparedStmtType preparedStmt;
1700     ISC_STATUS status_vector[20];
1701     XSQLVAR *sqlvar;
1702     struct tm tm_time;
1703     errInfoType err_info = OKAY_NO_ERROR;
1704 
1705   /* sqlBindDuration */
1706     logFunction(printf("sqlBindDuration(" FMT_U_MEM ", " FMT_D ", P"
1707                                           FMT_D "Y" FMT_D "M" FMT_D "DT"
1708                                           FMT_D "H" FMT_D "M%s" FMT_U "." F_U(06) "S)\n",
1709                        (memSizeType) sqlStatement, pos,
1710                        year, month, day, hour, minute,
1711                        second < 0 || micro_second < 0 ? "-" : "",
1712                        intAbs(second), intAbs(micro_second)););
1713     preparedStmt = (preparedStmtType) sqlStatement;
1714     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
1715       logError(printf("sqlBindDuration: pos: " FMT_D ", max pos: %hd.\n",
1716                       pos, preparedStmt->in_sqlda->sqld););
1717       raise_error(RANGE_ERROR);
1718     } else if (unlikely(year < -INT_MAX || year > INT_MAX || month < -12 || month > 12 ||
1719                         day < -31 || day > 31 || hour <= -24 || hour >= 24 ||
1720                         minute <= -60 || minute >= 60 || second <= -60 || second >= 60 ||
1721                         micro_second <= -1000000 || micro_second >= 1000000)) {
1722       logError(printf("sqlBindDuration: Duration not in allowed range.\n"););
1723       raise_error(RANGE_ERROR);
1724     } else {
1725       if (preparedStmt->executeSuccessful) {
1726         if (unlikely((isc_dsql_free_statement(status_vector,
1727                                               &preparedStmt->ppStmt,
1728                                               DSQL_close),
1729                       status_vector[0] == 1 && status_vector[1] != 0))) {
1730           setDbErrorMsg("sqlBindDuration", "isc_dsql_free_statement",
1731                         status_vector);
1732           logError(printf("sqlBindDuration: isc_dsql_free_statement error:\n%s\n",
1733                           dbError.message););
1734           err_info = DATABASE_ERROR;
1735         } else {
1736           preparedStmt->executeSuccessful = FALSE;
1737         } /* if */
1738       } /* if */
1739       if (likely(err_info == OKAY_NO_ERROR)) {
1740         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
1741         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
1742         switch (sqlvar->sqltype & ~1) {
1743             case SQL_TIMESTAMP:
1744               tm_time.tm_year = (int) year;
1745               tm_time.tm_mon  = (int) month;
1746               tm_time.tm_mday = (int) day;
1747               tm_time.tm_hour = (int) hour;
1748               tm_time.tm_min  = (int) minute;
1749               tm_time.tm_sec  = (int) second;
1750               isc_encode_timestamp(&tm_time, (ISC_TIMESTAMP *) sqlvar->sqldata);
1751               break;
1752             case SQL_TYPE_TIME:
1753               tm_time.tm_year = (int) year;
1754               tm_time.tm_mon  = (int) month;
1755               tm_time.tm_mday = (int) day;
1756               tm_time.tm_hour = (int) hour;
1757               tm_time.tm_min  = (int) minute;
1758               tm_time.tm_sec  = (int) second;
1759               isc_encode_sql_time(&tm_time, (ISC_TIME *) sqlvar->sqldata);
1760               break;
1761             case SQL_TYPE_DATE:
1762               tm_time.tm_year = (int) year;
1763               tm_time.tm_mon  = (int) month;
1764               tm_time.tm_mday = (int) day;
1765               tm_time.tm_hour = (int) hour;
1766               tm_time.tm_min  = (int) minute;
1767               tm_time.tm_sec  = (int) second;
1768               isc_encode_sql_date(&tm_time, (ISC_DATE *) sqlvar->sqldata);
1769               break;
1770           default:
1771             logError(printf("sqlBindDuration: Parameter " FMT_D " has the unknown type %s.\n",
1772                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
1773             err_info = RANGE_ERROR;
1774             break;
1775         } /* switch */
1776         if (likely(err_info == OKAY_NO_ERROR)) {
1777           if (sqlvar->sqltype & 1) {
1778             *sqlvar->sqlind = 0;
1779           } /* if */
1780           preparedStmt->fetchOkay = FALSE;
1781           preparedStmt->param_array[pos - 1].bound = TRUE;
1782         } /* if */
1783       } /* if */
1784       if (unlikely(err_info != OKAY_NO_ERROR)) {
1785         raise_error(err_info);
1786       } /* if */
1787     } /* if */
1788   } /* sqlBindDuration */
1789 
1790 
1791 
sqlBindFloat(sqlStmtType sqlStatement,intType pos,floatType value)1792 static void sqlBindFloat (sqlStmtType sqlStatement, intType pos, floatType value)
1793 
1794   {
1795     preparedStmtType preparedStmt;
1796     ISC_STATUS status_vector[20];
1797     XSQLVAR *sqlvar;
1798     errInfoType err_info = OKAY_NO_ERROR;
1799 
1800   /* sqlBindFloat */
1801     logFunction(printf("sqlBindFloat(" FMT_U_MEM ", " FMT_D ", " FMT_E ")\n",
1802                        (memSizeType) sqlStatement, pos, value););
1803     preparedStmt = (preparedStmtType) sqlStatement;
1804     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
1805       logError(printf("sqlBindFloat: pos: " FMT_D ", max pos: %hd.\n",
1806                       pos, preparedStmt->in_sqlda->sqld););
1807       raise_error(RANGE_ERROR);
1808     } else {
1809       if (preparedStmt->executeSuccessful) {
1810         if (unlikely((isc_dsql_free_statement(status_vector,
1811                                               &preparedStmt->ppStmt,
1812                                               DSQL_close),
1813                       status_vector[0] == 1 && status_vector[1] != 0))) {
1814           setDbErrorMsg("sqlBindFloat", "isc_dsql_free_statement",
1815                         status_vector);
1816           logError(printf("sqlBindFloat: isc_dsql_free_statement error:\n%s\n",
1817                           dbError.message););
1818           err_info = DATABASE_ERROR;
1819         } else {
1820           preparedStmt->executeSuccessful = FALSE;
1821         } /* if */
1822       } /* if */
1823       if (likely(err_info == OKAY_NO_ERROR)) {
1824         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
1825         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
1826         switch (sqlvar->sqltype & ~1) {
1827           case SQL_FLOAT:
1828             *(float *) sqlvar->sqldata = (float) value;
1829             break;
1830           case SQL_DOUBLE:
1831             *(double *) sqlvar->sqldata = (double) value;
1832             break;
1833           default:
1834             logError(printf("sqlBindFloat: Parameter " FMT_D " has the unknown type %s.\n",
1835                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
1836             err_info = RANGE_ERROR;
1837             break;
1838         } /* switch */
1839         if (likely(err_info == OKAY_NO_ERROR)) {
1840           if (sqlvar->sqltype & 1) {
1841             *sqlvar->sqlind = 0;
1842           } /* if */
1843           preparedStmt->fetchOkay = FALSE;
1844           preparedStmt->param_array[pos - 1].bound = TRUE;
1845         } /* if */
1846       } /* if */
1847       if (unlikely(err_info != OKAY_NO_ERROR)) {
1848         raise_error(err_info);
1849       } /* if */
1850     } /* if */
1851   } /* sqlBindFloat */
1852 
1853 
1854 
sqlBindInt(sqlStmtType sqlStatement,intType pos,intType value)1855 static void sqlBindInt (sqlStmtType sqlStatement, intType pos, intType value)
1856 
1857   {
1858     preparedStmtType preparedStmt;
1859     ISC_STATUS status_vector[20];
1860     XSQLVAR *sqlvar;
1861     char decimalInt[INTTYPE_DECIMAL_SIZE + NULL_TERMINATION_LEN];
1862     int decimalLength;
1863     errInfoType err_info = OKAY_NO_ERROR;
1864 
1865   /* sqlBindInt */
1866     logFunction(printf("sqlBindInt(" FMT_U_MEM ", " FMT_D ", " FMT_D ")\n",
1867                        (memSizeType) sqlStatement, pos, value););
1868     preparedStmt = (preparedStmtType) sqlStatement;
1869     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
1870       logError(printf("sqlBindInt: pos: " FMT_D ", max pos: %hd.\n",
1871                       pos, preparedStmt->in_sqlda->sqld););
1872       raise_error(RANGE_ERROR);
1873     } else {
1874       if (preparedStmt->executeSuccessful) {
1875         if (unlikely((isc_dsql_free_statement(status_vector,
1876                                               &preparedStmt->ppStmt,
1877                                               DSQL_close),
1878                       status_vector[0] == 1 && status_vector[1] != 0))) {
1879           setDbErrorMsg("sqlBindInt", "isc_dsql_free_statement",
1880                         status_vector);
1881           logError(printf("sqlBindInt: isc_dsql_free_statement error:\n%s\n",
1882                           dbError.message););
1883           err_info = DATABASE_ERROR;
1884         } else {
1885           preparedStmt->executeSuccessful = FALSE;
1886         } /* if */
1887       } /* if */
1888       if (likely(err_info == OKAY_NO_ERROR)) {
1889         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
1890         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
1891         switch (sqlvar->sqltype & ~1) {
1892           case SQL_SHORT:
1893             if (unlikely(value < INT16TYPE_MIN || value > INT16TYPE_MAX)) {
1894               logError(printf("sqlBindInt: Parameter " FMT_D ": "
1895                               FMT_D " does not fit into a 16-bit integer.\n",
1896                               pos, value));
1897               err_info = RANGE_ERROR;
1898             } else {
1899               *(int16Type *) sqlvar->sqldata = (int16Type) value;
1900             } /* if */
1901             break;
1902           case SQL_LONG:
1903             if (unlikely(value < INT32TYPE_MIN || value > INT32TYPE_MAX)) {
1904               logError(printf("sqlBindInt: Parameter " FMT_D ": "
1905                               FMT_D " does not fit into a 32-bit integer.\n",
1906                               pos, value));
1907               err_info = RANGE_ERROR;
1908             } else {
1909               *(int32Type *) sqlvar->sqldata = (int32Type) value;
1910             } /* if */
1911             break;
1912           case SQL_INT64:
1913             /* printf("sqlBindInt: scale: %hd\n", sqlvar->sqlscale); */
1914             if (sqlvar->sqlscale == 0) {
1915               *(int64Type *) sqlvar->sqldata = value;
1916             } else {
1917               *(int64Type *) sqlvar->sqldata = intToScaledInt64(value,
1918                   -sqlvar->sqlscale, &err_info);
1919             } /* if */
1920             break;
1921           case SQL_FLOAT:
1922             *(float *) sqlvar->sqldata = (float) value;
1923             break;
1924           case SQL_DOUBLE:
1925             *(double *) sqlvar->sqldata = (double) value;
1926             break;
1927           case SQL_TEXT:
1928             decimalLength = sprintf(decimalInt, FMT_D, value);
1929             if (unlikely(sqlvar->sqllen < decimalLength)) {
1930               logError(printf("sqlBindInt: Parameter " FMT_D ": "
1931                               "Decimal representation of " FMT_D
1932                               " longer than allowed (%hd).\n",
1933                               pos, value, sqlvar->sqllen););
1934               err_info = RANGE_ERROR;
1935             } else {
1936               memcpy(sqlvar->sqldata, decimalInt, (memSizeType) decimalLength);
1937               memset(&sqlvar->sqldata[decimalLength], ' ',
1938                   (memSizeType) sqlvar->sqllen - (memSizeType) decimalLength);
1939             } /* if */
1940             break;
1941           case SQL_VARYING:
1942             decimalLength = sprintf(decimalInt, FMT_D, value);
1943             if (unlikely(sqlvar->sqllen < decimalLength)) {
1944               logError(printf("sqlBindInt: Parameter " FMT_D ": "
1945                               "Decimal representation of " FMT_D
1946                               " longer than allowed (%hd).\n",
1947                               pos, value, sqlvar->sqllen););
1948               err_info = RANGE_ERROR;
1949             } else {
1950               *(int16Type *) sqlvar->sqldata = (int16Type) decimalLength;
1951               memcpy(&sqlvar->sqldata[sizeof(uint16Type)], decimalInt,
1952                   (memSizeType) decimalLength);
1953               memset(&sqlvar->sqldata[sizeof(uint16Type) + (memSizeType) decimalLength],
1954                   '\0', (memSizeType) sqlvar->sqllen -
1955                   (memSizeType) decimalLength);
1956             } /* if */
1957             break;
1958           default:
1959             logError(printf("sqlBindInt: Parameter " FMT_D " has the unknown type %s.\n",
1960                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
1961             err_info = RANGE_ERROR;
1962             break;
1963         } /* switch */
1964         if (likely(err_info == OKAY_NO_ERROR)) {
1965           if (sqlvar->sqltype & 1) {
1966             *sqlvar->sqlind = 0;
1967           } /* if */
1968           preparedStmt->fetchOkay = FALSE;
1969           preparedStmt->param_array[pos - 1].bound = TRUE;
1970         } /* if */
1971       } /* if */
1972       if (unlikely(err_info != OKAY_NO_ERROR)) {
1973         raise_error(err_info);
1974       } /* if */
1975     } /* if */
1976   } /* sqlBindInt */
1977 
1978 
1979 
sqlBindNull(sqlStmtType sqlStatement,intType pos)1980 static void sqlBindNull (sqlStmtType sqlStatement, intType pos)
1981 
1982   {
1983     preparedStmtType preparedStmt;
1984     ISC_STATUS status_vector[20];
1985     XSQLVAR *sqlvar;
1986     errInfoType err_info = OKAY_NO_ERROR;
1987 
1988   /* sqlBindNull */
1989     logFunction(printf("sqlBindNull(" FMT_U_MEM ", " FMT_D ")\n",
1990                        (memSizeType) sqlStatement, pos););
1991     preparedStmt = (preparedStmtType) sqlStatement;
1992     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
1993       logError(printf("sqlBindNull: pos: " FMT_D ", max pos: %hd.\n",
1994                       pos, preparedStmt->in_sqlda->sqld););
1995       raise_error(RANGE_ERROR);
1996     } else {
1997       if (preparedStmt->executeSuccessful) {
1998         if (unlikely((isc_dsql_free_statement(status_vector,
1999                                               &preparedStmt->ppStmt,
2000                                               DSQL_close),
2001                       status_vector[0] == 1 && status_vector[1] != 0))) {
2002           setDbErrorMsg("sqlBindNull", "isc_dsql_free_statement",
2003                         status_vector);
2004           logError(printf("sqlBindNull: isc_dsql_free_statement error:\n%s\n",
2005                           dbError.message););
2006           err_info = DATABASE_ERROR;
2007         } else {
2008           preparedStmt->executeSuccessful = FALSE;
2009         } /* if */
2010       } /* if */
2011       if (likely(err_info == OKAY_NO_ERROR)) {
2012         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
2013         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2014         if (sqlvar->sqltype & 1) {
2015           *sqlvar->sqlind = -1;
2016         } /* if */
2017         preparedStmt->fetchOkay = FALSE;
2018         preparedStmt->param_array[pos - 1].bound = TRUE;
2019       } /* if */
2020     } /* if */
2021   } /* sqlBindNull */
2022 
2023 
2024 
sqlBindStri(sqlStmtType sqlStatement,intType pos,const const_striType stri)2025 static void sqlBindStri (sqlStmtType sqlStatement, intType pos,
2026     const const_striType stri)
2027 
2028   {
2029     preparedStmtType preparedStmt;
2030     ISC_STATUS status_vector[20];
2031     XSQLVAR *sqlvar;
2032     cstriType stri8;
2033     memSizeType length;
2034     bstriType bstri;
2035     errInfoType err_info = OKAY_NO_ERROR;
2036 
2037   /* sqlBindStri */
2038     logFunction(printf("sqlBindStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
2039                        (memSizeType) sqlStatement, pos, striAsUnquotedCStri(stri)););
2040     preparedStmt = (preparedStmtType) sqlStatement;
2041     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
2042       logError(printf("sqlBindStri: pos: " FMT_D ", max pos: %hd.\n",
2043                       pos, preparedStmt->in_sqlda->sqld););
2044       raise_error(RANGE_ERROR);
2045     } else {
2046       if (preparedStmt->executeSuccessful) {
2047         if (unlikely((isc_dsql_free_statement(status_vector,
2048                                               &preparedStmt->ppStmt,
2049                                               DSQL_close),
2050                       status_vector[0] == 1 && status_vector[1] != 0))) {
2051           setDbErrorMsg("sqlBindStri", "isc_dsql_free_statement",
2052                         status_vector);
2053           logError(printf("sqlBindStri: isc_dsql_free_statement error:\n%s\n",
2054                           dbError.message););
2055           err_info = DATABASE_ERROR;
2056         } else {
2057           preparedStmt->executeSuccessful = FALSE;
2058         } /* if */
2059       } /* if */
2060       if (likely(err_info == OKAY_NO_ERROR)) {
2061         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
2062         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2063         switch (sqlvar->sqltype & ~1) {
2064           case SQL_TEXT:
2065             stri8 = stri_to_cstri8_buf(stri, &length);
2066             if (unlikely(stri8 == NULL)) {
2067               err_info = MEMORY_ERROR;
2068             } else {
2069               /* setupParameters() has already checked that sqllen > 0 holds */
2070               if (unlikely((memSizeType) sqlvar->sqllen < length)) {
2071                 logError(printf("sqlBindStri(*, " FMT_D ", \"%s\"): "
2072                                 "UTF-8 length (" FMT_U_MEM ") longer than allowed (%hd).\n",
2073                                 pos, striAsUnquotedCStri(stri), length, sqlvar->sqllen););
2074                 err_info = RANGE_ERROR;
2075               } else {
2076                 memcpy(sqlvar->sqldata, stri8, length);
2077                 memset(&sqlvar->sqldata[length], ' ',
2078                        (memSizeType) sqlvar->sqllen - length);
2079               } /* if */
2080               free(stri8);
2081             } /* if */
2082             break;
2083           case SQL_VARYING:
2084             stri8 = stri_to_cstri8_buf(stri, &length);
2085             if (unlikely(stri8 == NULL)) {
2086               err_info = MEMORY_ERROR;
2087             } else {
2088               /* setupParameters() has already checked that sqllen > 0 holds */
2089               if (unlikely((memSizeType) sqlvar->sqllen < length)) {
2090                 logError(printf("sqlBindStri(*, " FMT_D ", \"%s\"): "
2091                                 "UTF-8 length (" FMT_U_MEM ") longer than allowed (%hd).\n",
2092                                 pos, striAsUnquotedCStri(stri), length, sqlvar->sqllen););
2093                 err_info = RANGE_ERROR;
2094               } else {
2095                 *(int16Type *) sqlvar->sqldata = (int16Type) length;
2096                 memcpy(&sqlvar->sqldata[sizeof(uint16Type)], stri8, length);
2097                 memset(&sqlvar->sqldata[sizeof(uint16Type) + length], '\0',
2098                        (memSizeType) sqlvar->sqllen - length);
2099               } /* if */
2100               free(stri8);
2101             } /* if */
2102             break;
2103           case SQL_BLOB:
2104             if (sqlvar->sqlsubtype == 1) {
2105               /* BLOB SUB_TYPE 1 means essentially: textual Blob. */
2106               bstri = stri_to_bstri8(stri);
2107               if (unlikely(bstri == NULL)) {
2108                 err_info = MEMORY_ERROR;
2109               } else {
2110                 err_info = putBlob(preparedStmt, bstri, sqlvar);
2111                 FREE_BSTRI(bstri, bstri->size);
2112               } /* if */
2113             } else {
2114               /* BLOB SUB_TYPE 0 is a binary Blob. */
2115               logError(printf("sqlBindStri: Parameter " FMT_D " is a BLOB column.\n", pos););
2116               err_info = RANGE_ERROR;
2117             } /* if */
2118             break;
2119           default:
2120             logError(printf("sqlBindStri: Parameter " FMT_D " has the unknown type %s.\n",
2121                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
2122             err_info = RANGE_ERROR;
2123             break;
2124         } /* switch */
2125         if (likely(err_info == OKAY_NO_ERROR)) {
2126           if (sqlvar->sqltype & 1) {
2127             *sqlvar->sqlind = 0;
2128           } /* if */
2129           preparedStmt->fetchOkay = FALSE;
2130           preparedStmt->param_array[pos - 1].bound = TRUE;
2131         } /* if */
2132       } /* if */
2133       if (unlikely(err_info != OKAY_NO_ERROR)) {
2134         raise_error(err_info);
2135       } /* if */
2136     } /* if */
2137   } /* sqlBindStri */
2138 
2139 
2140 
sqlBindTime(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second,intType time_zone)2141 static void sqlBindTime (sqlStmtType sqlStatement, intType pos,
2142     intType year, intType month, intType day, intType hour,
2143     intType minute, intType second, intType micro_second,
2144     intType time_zone)
2145 
2146   {
2147     preparedStmtType preparedStmt;
2148     ISC_STATUS status_vector[20];
2149     XSQLVAR *sqlvar;
2150     struct tm tm_time;
2151     errInfoType err_info = OKAY_NO_ERROR;
2152 
2153   /* sqlBindTime */
2154     logFunction(printf("sqlBindTime(" FMT_U_MEM ", " FMT_D ", "
2155                        F_D(04) "-" F_D(02) "-" F_D(02) " "
2156                        F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ", "
2157                        FMT_D ")\n",
2158                        (memSizeType) sqlStatement, pos,
2159                        year, month, day,
2160                        hour, minute, second, micro_second,
2161                        time_zone););
2162     preparedStmt = (preparedStmtType) sqlStatement;
2163     if (unlikely(pos < 1 || pos > preparedStmt->in_sqlda->sqld)) {
2164       logError(printf("sqlBindTime: pos: " FMT_D ", max pos: %hd.\n",
2165                       pos, preparedStmt->in_sqlda->sqld););
2166       raise_error(RANGE_ERROR);
2167     } else if (unlikely(year < INT_MIN + 1900 || year > INT_MAX ||
2168                         month < 1 || month > 12 || day < 1 || day > 31 ||
2169                         hour < 0 || hour >= 24 || minute < 0 ||
2170                         minute >= 60 || second < 0 || second >= 60 ||
2171                         micro_second < 0 || micro_second >= 1000000)) {
2172       logError(printf("sqlBindTime: Time not in allowed range.\n"););
2173       raise_error(RANGE_ERROR);
2174     } else {
2175       if (preparedStmt->executeSuccessful) {
2176         if (unlikely((isc_dsql_free_statement(status_vector,
2177                                               &preparedStmt->ppStmt,
2178                                               DSQL_close),
2179                       status_vector[0] == 1 && status_vector[1] != 0))) {
2180           setDbErrorMsg("sqlBindTime", "isc_dsql_free_statement",
2181                         status_vector);
2182           logError(printf("sqlBindTime: isc_dsql_free_statement error:\n%s\n",
2183                           dbError.message););
2184           err_info = DATABASE_ERROR;
2185         } else {
2186           preparedStmt->executeSuccessful = FALSE;
2187         } /* if */
2188       } /* if */
2189       if (likely(err_info == OKAY_NO_ERROR)) {
2190         sqlvar = &preparedStmt->in_sqlda->sqlvar[pos - 1];
2191         /* printf("paramType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2192         switch (sqlvar->sqltype & ~1) {
2193             case SQL_TIMESTAMP:
2194               tm_time.tm_year = (int) year - 1900;
2195               tm_time.tm_mon  = (int) month - 1;
2196               tm_time.tm_mday = (int) day;
2197               tm_time.tm_hour = (int) hour;
2198               tm_time.tm_min  = (int) minute;
2199               tm_time.tm_sec  = (int) second;
2200               isc_encode_timestamp(&tm_time, (ISC_TIMESTAMP *) sqlvar->sqldata);
2201               ((ISC_TIMESTAMP *) sqlvar->sqldata)->timestamp_time += (ISC_TIME) micro_second / 100;
2202               break;
2203             case SQL_TYPE_TIME:
2204               tm_time.tm_year = (int) year - 1900;
2205               tm_time.tm_mon  = (int) month - 1;
2206               tm_time.tm_mday = (int) day;
2207               tm_time.tm_hour = (int) hour;
2208               tm_time.tm_min  = (int) minute;
2209               tm_time.tm_sec  = (int) second;
2210               isc_encode_sql_time(&tm_time, (ISC_TIME *) sqlvar->sqldata);
2211               *(ISC_TIME *) sqlvar->sqldata += (ISC_TIME) micro_second / 100;
2212               break;
2213             case SQL_TYPE_DATE:
2214               tm_time.tm_year = (int) year - 1900;
2215               tm_time.tm_mon  = (int) month - 1;
2216               tm_time.tm_mday = (int) day;
2217               tm_time.tm_hour = (int) hour;
2218               tm_time.tm_min  = (int) minute;
2219               tm_time.tm_sec  = (int) second;
2220               isc_encode_sql_date(&tm_time, (ISC_DATE *) sqlvar->sqldata);
2221               break;
2222           default:
2223             logError(printf("sqlBindTime: Parameter " FMT_D " has the unknown type %s.\n",
2224                             pos, nameOfSqlType(sqlvar->sqltype & ~1)););
2225             err_info = RANGE_ERROR;
2226             break;
2227         } /* switch */
2228         if (likely(err_info == OKAY_NO_ERROR)) {
2229           if (sqlvar->sqltype & 1) {
2230             *sqlvar->sqlind = 0;
2231           } /* if */
2232           preparedStmt->fetchOkay = FALSE;
2233           preparedStmt->param_array[pos - 1].bound = TRUE;
2234         } /* if */
2235       } /* if */
2236       if (unlikely(err_info != OKAY_NO_ERROR)) {
2237         raise_error(err_info);
2238       } /* if */
2239     } /* if */
2240   } /* sqlBindTime */
2241 
2242 
2243 
sqlClose(databaseType database)2244 static void sqlClose (databaseType database)
2245 
2246   {
2247     dbType db;
2248     ISC_STATUS status_vector[20];
2249     errInfoType err_info = OKAY_NO_ERROR;
2250 
2251   /* sqlClose */
2252     logFunction(printf("sqlClose(" FMT_U_MEM ")\n",
2253                        (memSizeType) database););
2254     db = (dbType) database;
2255     if (db->connection != 0) {
2256       if (db->trans_handle != 0) {
2257         isc_commit_transaction(status_vector,
2258                                &db->trans_handle);
2259         if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
2260           setDbErrorMsg("sqlClose", "isc_commit_transaction",
2261                         status_vector);
2262           logError(printf("sqlClose: isc_commit_transaction error:\n%s\n",
2263                           dbError.message););
2264           err_info = DATABASE_ERROR;
2265         } else {
2266           db->trans_handle = 0;
2267         } /* if */
2268       } /* if */
2269       if (likely(err_info == OKAY_NO_ERROR)) {
2270         isc_detach_database(status_vector,
2271                             &db->connection);
2272         if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
2273           setDbErrorMsg("sqlClose", "isc_detach_database",
2274                         status_vector);
2275           logError(printf("sqlClose: isc_detach_database error:\n%s\n",
2276                           dbError.message););
2277           err_info = DATABASE_ERROR;
2278         } else {
2279           db->connection = 0;
2280         } /* if */
2281       } /* if */
2282       if (unlikely(err_info != OKAY_NO_ERROR)) {
2283         raise_error(err_info);
2284       } /* if */
2285     } /* if */
2286     logFunction(printf("sqlClose -->\n"););
2287   } /* sqlClose */
2288 
2289 
2290 
sqlColumnBigInt(sqlStmtType sqlStatement,intType column)2291 static bigIntType sqlColumnBigInt (sqlStmtType sqlStatement, intType column)
2292 
2293   {
2294     preparedStmtType preparedStmt;
2295     XSQLVAR *sqlvar;
2296     short *sqlind;
2297     bigIntType columnValue;
2298 
2299   /* sqlColumnBigInt */
2300     logFunction(printf("sqlColumnBigInt(" FMT_U_MEM ", " FMT_D ")\n",
2301                        (memSizeType) sqlStatement, column););
2302     preparedStmt = (preparedStmtType) sqlStatement;
2303     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2304                  column > preparedStmt->out_sqlda->sqld)) {
2305       logError(printf("sqlColumnBigInt: Fetch okay: %d, column: " FMT_D
2306                       ", max column: %hd.\n",
2307                       preparedStmt->fetchOkay, column,
2308                       preparedStmt->out_sqlda->sqld););
2309       raise_error(RANGE_ERROR);
2310       columnValue = NULL;
2311     } else {
2312       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
2313       sqlind = sqlvar->sqlind;
2314       if (sqlind != NULL && *sqlind == -1) {
2315         /* printf("Column is NULL -> Use default value: 0\n"); */
2316         columnValue = bigZero();
2317       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
2318         dbInconsistent("sqlColumnBigInt", "sqlind");
2319         logError(printf("sqlColumnBigInt: Column " FMT_D ": "
2320                         "sqlind has the value %d.\n",
2321                         column, *sqlind););
2322         raise_error(DATABASE_ERROR);
2323         columnValue = NULL;
2324       } else {
2325         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2326         switch (sqlvar->sqltype & ~1) {
2327           case SQL_SHORT:
2328             if (unlikely(sqlvar->sqlscale != 0)) {
2329               logError(printf("sqlColumnBigInt: Column " FMT_D ": "
2330                               "The scale of an integer field must be 0.\n", column););
2331               raise_error(RANGE_ERROR);
2332               columnValue = NULL;
2333             } else {
2334               columnValue = bigFromInt32((int32Type) *(int16Type *) sqlvar->sqldata);
2335             } /* if */
2336             break;
2337           case SQL_LONG:
2338             if (unlikely(sqlvar->sqlscale != 0)) {
2339               logError(printf("sqlColumnBigInt: Column " FMT_D ": "
2340                               "The scale of an integer field must be 0.\n", column););
2341               raise_error(RANGE_ERROR);
2342               columnValue = NULL;
2343             } else {
2344               columnValue = bigFromInt32(*(int32Type *) sqlvar->sqldata);
2345             } /* if */
2346             break;
2347           case SQL_INT64:
2348             if (unlikely(sqlvar->sqlscale != 0)) {
2349               logError(printf("sqlColumnBigInt: Column " FMT_D ": "
2350                               "The scale of an integer field must be 0.\n", column););
2351               raise_error(RANGE_ERROR);
2352               columnValue = NULL;
2353             } else {
2354               columnValue = bigFromInt64(*(int64Type *) sqlvar->sqldata);
2355             } /* if */
2356             break;
2357           default:
2358             logError(printf("sqlColumnBigInt: Column " FMT_D " has the unknown type %s.\n",
2359                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
2360             raise_error(RANGE_ERROR);
2361             columnValue = NULL;
2362             break;
2363         } /* switch */
2364       } /* if */
2365     } /* if */
2366     logFunction(printf("sqlColumnBigInt --> %s\n", bigHexCStri(columnValue)););
2367     return columnValue;
2368   } /* sqlColumnBigInt */
2369 
2370 
2371 
sqlColumnBigRat(sqlStmtType sqlStatement,intType column,bigIntType * numerator,bigIntType * denominator)2372 static void sqlColumnBigRat (sqlStmtType sqlStatement, intType column,
2373     bigIntType *numerator, bigIntType *denominator)
2374 
2375   {
2376     preparedStmtType preparedStmt;
2377     XSQLVAR *sqlvar;
2378     short *sqlind;
2379     float floatValue;
2380     double doubleValue;
2381 
2382   /* sqlColumnBigRat */
2383     logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", *, *)\n",
2384                        (memSizeType) sqlStatement, column););
2385     preparedStmt = (preparedStmtType) sqlStatement;
2386     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2387                  column > preparedStmt->out_sqlda->sqld)) {
2388       logError(printf("sqlColumnBigRat: Fetch okay: %d, column: " FMT_D
2389                       ", max column: %hd.\n",
2390                       preparedStmt->fetchOkay, column,
2391                       preparedStmt->out_sqlda->sqld););
2392       raise_error(RANGE_ERROR);
2393     } else {
2394       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
2395       sqlind = sqlvar->sqlind;
2396       if (sqlind != NULL && *sqlind == -1) {
2397         /* printf("Column is NULL -> Use default value: 0\n"); */
2398         *numerator = bigZero();
2399         *denominator = bigFromInt32(1);
2400       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
2401         dbInconsistent("sqlColumnBigRat", "sqlind");
2402         logError(printf("sqlColumnBigRat: Column " FMT_D ": "
2403                         "sqlind has the value %d.\n",
2404                         column, *sqlind););
2405         raise_error(DATABASE_ERROR);
2406       } else {
2407         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2408         switch (sqlvar->sqltype & ~1) {
2409           case SQL_SHORT:
2410             *numerator = bigFromInt32((int32Type)
2411                 *(int16Type *) sqlvar->sqldata);
2412             if (sqlvar->sqlscale == 0) {
2413               *denominator = bigFromInt32(1);
2414             } else {
2415               *denominator = bigIPowSignedDigit(10, -sqlvar->sqlscale);
2416             } /* if */
2417             break;
2418           case SQL_LONG:
2419             *numerator = bigFromInt32(*(int32Type *) sqlvar->sqldata);
2420             if (sqlvar->sqlscale == 0) {
2421               *denominator = bigFromInt32(1);
2422             } else {
2423               *denominator = bigIPowSignedDigit(10, -sqlvar->sqlscale);
2424             } /* if */
2425             break;
2426           case SQL_INT64:
2427             *numerator = bigFromInt64(*(int64Type *) sqlvar->sqldata);
2428             if (sqlvar->sqlscale == 0) {
2429               *denominator = bigFromInt32(1);
2430             } else {
2431               *denominator = bigIPowSignedDigit(10, -sqlvar->sqlscale);
2432             } /* if */
2433             break;
2434           case SQL_FLOAT:
2435             floatValue = *(float *) sqlvar->sqldata;
2436             /* printf("sqlColumnBigRat: float: %f\n", floatValue); */
2437             *numerator = roundDoubleToBigRat(floatValue, FALSE, denominator);
2438             break;
2439           case SQL_DOUBLE:
2440             doubleValue = *(double *) sqlvar->sqldata;
2441             /* printf("sqlColumnBigRat: double: %f\n", doubleValue); */
2442             *numerator = roundDoubleToBigRat(doubleValue, TRUE, denominator);
2443             break;
2444           default:
2445             logError(printf("sqlColumnBigRat: Column " FMT_D " has the unknown type %s.\n",
2446                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
2447             raise_error(RANGE_ERROR);
2448             break;
2449         } /* switch */
2450       } /* if */
2451     } /* if */
2452     logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s) -->\n",
2453                        (memSizeType) sqlStatement, column,
2454                        bigHexCStri(*numerator), bigHexCStri(*denominator)););
2455   } /* sqlColumnBigRat */
2456 
2457 
2458 
sqlColumnBool(sqlStmtType sqlStatement,intType column)2459 static boolType sqlColumnBool (sqlStmtType sqlStatement, intType column)
2460 
2461   {
2462     preparedStmtType preparedStmt;
2463     XSQLVAR *sqlvar;
2464     short *sqlind;
2465     intType columnValue;
2466 
2467   /* sqlColumnBool */
2468     logFunction(printf("sqlColumnBool(" FMT_U_MEM ", " FMT_D ")\n",
2469                        (memSizeType) sqlStatement, column););
2470     preparedStmt = (preparedStmtType) sqlStatement;
2471     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2472                  column > preparedStmt->out_sqlda->sqld)) {
2473       logError(printf("sqlColumnBool: Fetch okay: %d, column: " FMT_D
2474                       ", max column: %hd.\n",
2475                       preparedStmt->fetchOkay, column,
2476                       preparedStmt->out_sqlda->sqld););
2477       raise_error(RANGE_ERROR);
2478       columnValue = 0;
2479     } else {
2480       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
2481       sqlind = sqlvar->sqlind;
2482       if (sqlind != NULL && *sqlind == -1) {
2483         /* printf("Column is NULL -> Use default value: FALSE\n"); */
2484         columnValue = 0;
2485       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
2486         dbInconsistent("sqlColumnBool", "sqlind");
2487         logError(printf("sqlColumnBool: Column " FMT_D ": "
2488                         "sqlind has the value %d.\n",
2489                         column, *sqlind););
2490         raise_error(DATABASE_ERROR);
2491         columnValue = 0;
2492       } else {
2493         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2494         switch (sqlvar->sqltype & ~1) {
2495           case SQL_BOOLEAN:
2496           case SQL_SHORT:
2497             if (unlikely(sqlvar->sqlscale != 0)) {
2498               logError(printf("sqlColumnBool: Column " FMT_D ": "
2499                               "The scale of a boolean field must be 0.\n", column););
2500               raise_error(RANGE_ERROR);
2501               columnValue = 0;
2502             } else {
2503               columnValue = *(int16Type *) sqlvar->sqldata;
2504             } /* if */
2505             break;
2506           case SQL_LONG:
2507             if (unlikely(sqlvar->sqlscale != 0)) {
2508               logError(printf("sqlColumnBool: Column " FMT_D ": "
2509                               "The scale of a boolean field must be 0.\n", column););
2510               raise_error(RANGE_ERROR);
2511               columnValue = 0;
2512             } else {
2513               columnValue = *(int32Type *) sqlvar->sqldata;
2514             } /* if */
2515             break;
2516           case SQL_INT64:
2517             if (unlikely(sqlvar->sqlscale != 0)) {
2518               logError(printf("sqlColumnBool: Column " FMT_D ": "
2519                               "The scale of a boolean field must be 0.\n", column););
2520               raise_error(RANGE_ERROR);
2521               columnValue = 0;
2522             } else {
2523               columnValue = *(int64Type *) sqlvar->sqldata;
2524             } /* if */
2525             break;
2526           case SQL_TEXT:
2527             if (unlikely(sqlvar->sqllen != 1)) {
2528               logError(printf("sqlColumnBool: Column " FMT_D ": "
2529                               "The size of a boolean field must be 1.\n", column););
2530               raise_error(RANGE_ERROR);
2531               columnValue = 0;
2532             } else {
2533               columnValue = ((char *) sqlvar->sqldata)[0] != '0';
2534             } /* if */
2535             break;
2536           default:
2537             logError(printf("sqlColumnBool: Column " FMT_D " has the unknown type %s.\n",
2538                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
2539             raise_error(RANGE_ERROR);
2540             columnValue = 0;
2541             break;
2542         } /* switch */
2543         if (unlikely((uintType) columnValue >= 2)) {
2544           logError(printf("sqlColumnBool: Column " FMT_D ": "
2545                           FMT_D " is not an allowed boolean value.\n",
2546                           column, columnValue););
2547           raise_error(RANGE_ERROR);
2548         } /* if */
2549       } /* if */
2550     } /* if */
2551     logFunction(printf("sqlColumnBool --> %s\n", columnValue ? "TRUE" : "FALSE"););
2552     return columnValue != 0;
2553   } /* sqlColumnBool */
2554 
2555 
2556 
sqlColumnBStri(sqlStmtType sqlStatement,intType column)2557 static bstriType sqlColumnBStri (sqlStmtType sqlStatement, intType column)
2558 
2559   {
2560     preparedStmtType preparedStmt;
2561     XSQLVAR *sqlvar;
2562     short *sqlind;
2563     short length;
2564     uint16Type varyingLength;
2565     errInfoType err_info = OKAY_NO_ERROR;
2566     bstriType columnValue;
2567 
2568   /* sqlColumnBStri */
2569     logFunction(printf("sqlColumnBStri(" FMT_U_MEM ", " FMT_D ")\n",
2570                        (memSizeType) sqlStatement, column););
2571     preparedStmt = (preparedStmtType) sqlStatement;
2572     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2573                  column > preparedStmt->out_sqlda->sqld)) {
2574       logError(printf("sqlColumnBStri: Fetch okay: %d, column: " FMT_D
2575                       ", max column: %hd.\n",
2576                       preparedStmt->fetchOkay, column,
2577                       preparedStmt->out_sqlda->sqld););
2578       raise_error(RANGE_ERROR);
2579       columnValue = NULL;
2580     } else {
2581       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
2582       sqlind = sqlvar->sqlind;
2583       if (sqlind != NULL && *sqlind == -1) {
2584         /* printf("Column is NULL -> Use default value: \"\"\n"); */
2585         if (unlikely(!ALLOC_BSTRI_SIZE_OK(columnValue, 0))) {
2586           raise_error(MEMORY_ERROR);
2587         } else {
2588           columnValue->size = 0;
2589         } /* if */
2590       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
2591         dbInconsistent("sqlColumnBStri", "sqlind");
2592         logError(printf("sqlColumnBStri: Column " FMT_D ": "
2593                         "sqlind has the value %d.\n",
2594                         column, *sqlind););
2595         raise_error(DATABASE_ERROR);
2596         columnValue = NULL;
2597       } else {
2598         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2599         switch (sqlvar->sqltype & ~1) {
2600           case SQL_TEXT:
2601             length = sqlvar->sqllen;
2602             /* printf("length: %hd\n", length); */
2603             while (length > 0 && sqlvar->sqldata[length - 1] == ' ') {
2604               length--;
2605             } /* if */
2606             if (unlikely(!ALLOC_BSTRI_CHECK_SIZE(columnValue, (memSizeType) length))) {
2607               raise_error(MEMORY_ERROR);
2608             } else {
2609               memcpy(columnValue->mem, sqlvar->sqldata, (memSizeType) length);
2610               columnValue->size = (memSizeType) length;
2611             } /* if */
2612             break;
2613           case SQL_VARYING:
2614             length = sqlvar->sqllen;
2615             /* printf("length: %hd\n", length); */
2616             varyingLength = *(uint16Type *) sqlvar->sqldata;
2617             /* printf("varyingLength: " FMT_U16 "\n", varyingLength); */
2618             if (unlikely(varyingLength > length)) {
2619               dbInconsistent("sqlColumnBStri", "sqllen");
2620               logError(printf("sqlColumnBStri: Column " FMT_D ": "
2621                               "Length of SQL_VARYING " FMT_U16 " larger than field size %hd.\n",
2622                               column, varyingLength, length););
2623               raise_error(DATABASE_ERROR);
2624               columnValue = NULL;
2625             } else if (unlikely(!ALLOC_BSTRI_CHECK_SIZE(columnValue, (memSizeType) varyingLength))) {
2626               raise_error(MEMORY_ERROR);
2627             } else {
2628               memcpy(columnValue->mem,
2629                      &sqlvar->sqldata[sizeof(uint16Type)],
2630                      (memSizeType) varyingLength);
2631               columnValue->size = (memSizeType) varyingLength;
2632             } /* if */
2633             break;
2634           case SQL_BLOB:
2635             if (sqlvar->sqlsubtype == 1) {
2636               /* BLOB SUB_TYPE 1 means essentially: textual Blob. */
2637               logError(printf("sqlColumnBStri: Column " FMT_D " is a CLOB.\n",
2638                               column););
2639               raise_error(RANGE_ERROR);
2640               columnValue = NULL;
2641             } else {
2642               /* BLOB SUB_TYPE 0 is a binary Blob. */
2643               columnValue = getBlob(preparedStmt,
2644                                     (ISC_QUAD *) sqlvar->sqldata,
2645                                     &err_info);
2646               if (unlikely(columnValue == NULL)) {
2647                 raise_error(err_info);
2648               } /* if */
2649             } /* if */
2650             break;
2651           default:
2652             logError(printf("sqlColumnBStri: Column " FMT_D " has the unknown type %s.\n",
2653                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
2654             raise_error(RANGE_ERROR);
2655             columnValue = NULL;
2656             break;
2657         } /* switch */
2658       } /* if */
2659     } /* if */
2660     logFunction(printf("sqlColumnBStri --> \"%s\"\n", bstriAsUnquotedCStri(columnValue)););
2661     return columnValue;
2662   } /* sqlColumnBStri */
2663 
2664 
2665 
sqlColumnDuration(sqlStmtType sqlStatement,intType column,intType * year,intType * month,intType * day,intType * hour,intType * minute,intType * second,intType * micro_second)2666 static void sqlColumnDuration (sqlStmtType sqlStatement, intType column,
2667     intType *year, intType *month, intType *day, intType *hour,
2668     intType *minute, intType *second, intType *micro_second)
2669 
2670   {
2671     preparedStmtType preparedStmt;
2672     XSQLVAR *sqlvar;
2673     short *sqlind;
2674     struct tm tm_time;
2675 
2676   /* sqlColumnDuration */
2677     logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ", *)\n",
2678                        (memSizeType) sqlStatement, column););
2679     preparedStmt = (preparedStmtType) sqlStatement;
2680     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2681                  column > preparedStmt->out_sqlda->sqld)) {
2682       logError(printf("sqlColumnDuration: Fetch okay: %d, column: " FMT_D
2683                       ", max column: %hd.\n",
2684                       preparedStmt->fetchOkay, column,
2685                       preparedStmt->out_sqlda->sqld););
2686       raise_error(RANGE_ERROR);
2687     } else {
2688       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
2689       sqlind = sqlvar->sqlind;
2690       if (sqlind != NULL && *sqlind == -1) {
2691         /* printf("Column is NULL -> Use default value: P0D\n"); */
2692         *year         = 0;
2693         *month        = 0;
2694         *day          = 0;
2695         *hour         = 0;
2696         *minute       = 0;
2697         *second       = 0;
2698         *micro_second = 0;
2699       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
2700         dbInconsistent("sqlColumnDuration", "sqlind");
2701         logError(printf("sqlColumnDuration: Column " FMT_D ": "
2702                         "sqlind has the value %d.\n",
2703                         column, *sqlind););
2704         raise_error(DATABASE_ERROR);
2705       } else {
2706         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2707         switch (sqlvar->sqltype & ~1) {
2708           case SQL_TIMESTAMP:
2709             isc_decode_timestamp((ISC_TIMESTAMP *) sqlvar->sqldata, &tm_time);
2710             *year   = tm_time.tm_year;
2711             *month  = tm_time.tm_mon - 13;
2712             *day    = tm_time.tm_mday;
2713             *hour   = tm_time.tm_hour;
2714             *minute = tm_time.tm_min;
2715             *second = tm_time.tm_sec;
2716             *micro_second = 0;
2717             break;
2718           case SQL_TYPE_TIME:
2719             isc_decode_sql_time((ISC_TIME *) sqlvar->sqldata, &tm_time);
2720             *year   = tm_time.tm_year;
2721             *month  = tm_time.tm_mon;
2722             *day    = tm_time.tm_mday;
2723             *hour   = tm_time.tm_hour;
2724             *minute = tm_time.tm_min;
2725             *second = tm_time.tm_sec;
2726             *micro_second = 0;
2727             break;
2728           case SQL_TYPE_DATE:
2729             isc_decode_sql_date((ISC_DATE *) sqlvar->sqldata, &tm_time);
2730             *year   = tm_time.tm_year;
2731             *month  = tm_time.tm_mon;
2732             *day    = tm_time.tm_mday;
2733             *hour   = tm_time.tm_hour;
2734             *minute = tm_time.tm_min;
2735             *second = tm_time.tm_sec;
2736             *micro_second = 0;
2737             break;
2738           default:
2739             logError(printf("sqlColumnDuration: Column " FMT_D " has the unknown type %s.\n",
2740                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
2741             raise_error(RANGE_ERROR);
2742             break;
2743         } /* switch */
2744       } /* if */
2745     } /* if */
2746     logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ") --> P"
2747                                             FMT_D "Y" FMT_D "M" FMT_D "DT"
2748                                             FMT_D "H" FMT_D "M%s" FMT_U "." F_U(06) "S\n",
2749                        (memSizeType) sqlStatement, column,
2750                        *year, *month, *day, *hour, *minute,
2751                        *second < 0 || *micro_second < 0 ? "-" : "",
2752                        intAbs(*second), intAbs(*micro_second)););
2753   } /* sqlColumnDuration */
2754 
2755 
2756 
sqlColumnFloat(sqlStmtType sqlStatement,intType column)2757 static floatType sqlColumnFloat (sqlStmtType sqlStatement, intType column)
2758 
2759   {
2760     preparedStmtType preparedStmt;
2761     XSQLVAR *sqlvar;
2762     short *sqlind;
2763     floatType columnValue;
2764 
2765   /* sqlColumnFloat */
2766     logFunction(printf("sqlColumnFloat(" FMT_U_MEM ", " FMT_D ")\n",
2767                        (memSizeType) sqlStatement, column););
2768     preparedStmt = (preparedStmtType) sqlStatement;
2769     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2770                  column > preparedStmt->out_sqlda->sqld)) {
2771       logError(printf("sqlColumnFloat: Fetch okay: %d, column: " FMT_D
2772                       ", max column: %hd.\n",
2773                       preparedStmt->fetchOkay, column,
2774                       preparedStmt->out_sqlda->sqld););
2775       raise_error(RANGE_ERROR);
2776       columnValue = 0.0;
2777     } else {
2778       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
2779       sqlind = sqlvar->sqlind;
2780       if (sqlind != NULL && *sqlind == -1) {
2781         /* printf("Column is NULL -> Use default value: 0.0\n"); */
2782         columnValue = 0.0;
2783       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
2784         dbInconsistent("sqlColumnFloat", "sqlind");
2785         logError(printf("sqlColumnFloat: Column " FMT_D ": "
2786                         "sqlind has the value %d.\n",
2787                         column, *sqlind););
2788         raise_error(DATABASE_ERROR);
2789         columnValue = 0.0;
2790       } else {
2791         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2792         switch (sqlvar->sqltype & ~1) {
2793           case SQL_SHORT:
2794             if (sqlvar->sqlscale == 0) {
2795               columnValue = (floatType) *(int16Type *) sqlvar->sqldata;
2796             } else {
2797               columnValue = ((floatType) *(int16Type *) sqlvar->sqldata) /
2798                   fltIPow(10.0, -sqlvar->sqlscale);
2799             } /* if */
2800             break;
2801           case SQL_LONG:
2802             if (sqlvar->sqlscale == 0) {
2803               columnValue = (floatType) *(int32Type *) sqlvar->sqldata;
2804             } else {
2805               columnValue = ((floatType) *(int32Type *) sqlvar->sqldata) /
2806                   fltIPow(10.0, -sqlvar->sqlscale);
2807             } /* if */
2808             break;
2809           case SQL_INT64:
2810             if (sqlvar->sqlscale == 0) {
2811               columnValue = (floatType) *(int64Type *) sqlvar->sqldata;
2812             } else {
2813               columnValue = ((floatType) *(int64Type *) sqlvar->sqldata) /
2814                   fltIPow(10.0, -sqlvar->sqlscale);
2815             } /* if */
2816             break;
2817           case SQL_FLOAT:
2818             columnValue = *(float *) sqlvar->sqldata;
2819             break;
2820           case SQL_DOUBLE:
2821             columnValue = *(double *) sqlvar->sqldata;
2822             break;
2823           default:
2824             logError(printf("sqlColumnFloat: Column " FMT_D " has the unknown type %s.\n",
2825                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
2826             raise_error(RANGE_ERROR);
2827             columnValue = 0.0;
2828             break;
2829         } /* switch */
2830       } /* if */
2831     } /* if */
2832     logFunction(printf("sqlColumnFloat --> " FMT_E "\n", columnValue););
2833     return columnValue;
2834   } /* sqlColumnFloat */
2835 
2836 
2837 
sqlColumnInt(sqlStmtType sqlStatement,intType column)2838 static intType sqlColumnInt (sqlStmtType sqlStatement, intType column)
2839 
2840   {
2841     preparedStmtType preparedStmt;
2842     XSQLVAR *sqlvar;
2843     short *sqlind;
2844     intType columnValue;
2845 
2846   /* sqlColumnInt */
2847     logFunction(printf("sqlColumnInt(" FMT_U_MEM ", " FMT_D ")\n",
2848                        (memSizeType) sqlStatement, column););
2849     preparedStmt = (preparedStmtType) sqlStatement;
2850     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2851                  column > preparedStmt->out_sqlda->sqld)) {
2852       logError(printf("sqlColumnInt: Fetch okay: %d, column: " FMT_D
2853                       ", max column: %hd.\n",
2854                       preparedStmt->fetchOkay, column,
2855                       preparedStmt->out_sqlda->sqld););
2856       raise_error(RANGE_ERROR);
2857       columnValue = 0;
2858     } else {
2859       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
2860       sqlind = sqlvar->sqlind;
2861       if (sqlind != NULL && *sqlind == -1) {
2862         /* printf("Column is NULL -> Use default value: 0\n"); */
2863         columnValue = 0;
2864       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
2865         dbInconsistent("sqlColumnInt", "sqlind");
2866         logError(printf("sqlColumnInt: Column " FMT_D ": "
2867                         "sqlind has the value %d.\n",
2868                         column, *sqlind););
2869         raise_error(DATABASE_ERROR);
2870         columnValue = 0;
2871       } else {
2872         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2873         switch (sqlvar->sqltype & ~1) {
2874           case SQL_SHORT:
2875             if (unlikely(sqlvar->sqlscale != 0)) {
2876               logError(printf("sqlColumnInt: Column " FMT_D ": "
2877                               "The scale of an integer field must be 0.\n", column););
2878               raise_error(RANGE_ERROR);
2879               columnValue = 0;
2880             } else {
2881               columnValue = *(int16Type *) sqlvar->sqldata;
2882             } /* if */
2883             break;
2884           case SQL_LONG:
2885             if (unlikely(sqlvar->sqlscale != 0)) {
2886               logError(printf("sqlColumnInt: Column " FMT_D ": "
2887                               "The scale of an integer field must be 0.\n", column););
2888               raise_error(RANGE_ERROR);
2889               columnValue = 0;
2890             } else {
2891               columnValue = *(int32Type *) sqlvar->sqldata;
2892             } /* if */
2893             break;
2894           case SQL_INT64:
2895             if (unlikely(sqlvar->sqlscale != 0)) {
2896               logError(printf("sqlColumnInt: Column " FMT_D ": "
2897                               "The scale of an integer field must be 0.\n", column););
2898               raise_error(RANGE_ERROR);
2899               columnValue = 0;
2900             } else {
2901               columnValue = *(int64Type *) sqlvar->sqldata;
2902             } /* if */
2903             break;
2904           default:
2905             logError(printf("sqlColumnInt: Column " FMT_D " has the unknown type %s.\n",
2906                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
2907             raise_error(RANGE_ERROR);
2908             columnValue = 0;
2909             break;
2910         } /* switch */
2911       } /* if */
2912     } /* if */
2913     logFunction(printf("sqlColumnInt --> " FMT_D "\n", columnValue););
2914     return columnValue;
2915   } /* sqlColumnInt */
2916 
2917 
2918 
sqlColumnStri(sqlStmtType sqlStatement,intType column)2919 static striType sqlColumnStri (sqlStmtType sqlStatement, intType column)
2920 
2921   {
2922     preparedStmtType preparedStmt;
2923     XSQLVAR *sqlvar;
2924     short *sqlind;
2925     short length;
2926     uint16Type varyingLength;
2927     errInfoType err_info = OKAY_NO_ERROR;
2928     striType columnValue;
2929 
2930   /* sqlColumnStri */
2931     logFunction(printf("sqlColumnStri(" FMT_U_MEM ", " FMT_D ")\n",
2932                        (memSizeType) sqlStatement, column););
2933     preparedStmt = (preparedStmtType) sqlStatement;
2934     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
2935                  column > preparedStmt->out_sqlda->sqld)) {
2936       logError(printf("sqlColumnStri: Fetch okay: %d, column: " FMT_D
2937                       ", max column: %hd.\n",
2938                       preparedStmt->fetchOkay, column,
2939                       preparedStmt->out_sqlda->sqld););
2940       raise_error(RANGE_ERROR);
2941       columnValue = NULL;
2942     } else {
2943       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
2944       sqlind = sqlvar->sqlind;
2945       if (sqlind != NULL && *sqlind == -1) {
2946         /* printf("Column is NULL -> Use default value: \"\"\n"); */
2947         columnValue = strEmpty();
2948       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
2949         dbInconsistent("sqlColumnStri", "sqlind");
2950         logError(printf("sqlColumnStri: Column " FMT_D ": "
2951                         "sqlind has the value %d.\n",
2952                         column, *sqlind););
2953         raise_error(DATABASE_ERROR);
2954         columnValue = NULL;
2955       } else {
2956         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
2957         switch (sqlvar->sqltype & ~1) {
2958           case SQL_TEXT:
2959             length = sqlvar->sqllen;
2960             /* printf("length: %hd\n", length); */
2961             while (length > 0 && sqlvar->sqldata[length - 1] == ' ') {
2962               length--;
2963             } /* if */
2964             columnValue = cstri8_buf_to_stri(sqlvar->sqldata,
2965                 (memSizeType) length, &err_info);
2966             if (unlikely(columnValue == NULL)) {
2967               raise_error(err_info);
2968             } /* if */
2969             break;
2970           case SQL_VARYING:
2971             length = sqlvar->sqllen;
2972             /* printf("length: %hd\n", length); */
2973             varyingLength = *(uint16Type *) sqlvar->sqldata;
2974             /* printf("varyingLength: " FMT_U16 "\n", varyingLength); */
2975             if (unlikely(varyingLength > length)) {
2976               dbInconsistent("sqlColumnStri", "sqllen");
2977               logError(printf("sqlColumnStri: Column " FMT_D ": "
2978                               "Length of SQL_VARYING " FMT_U16 " larger than field size %hd.\n",
2979                               column, varyingLength, length););
2980               raise_error(DATABASE_ERROR);
2981               columnValue = NULL;
2982             } else {
2983               columnValue = cstri8_buf_to_stri(
2984                   &sqlvar->sqldata[sizeof(uint16Type)],
2985                   (memSizeType) varyingLength, &err_info);
2986               if (unlikely(columnValue == NULL)) {
2987                 raise_error(err_info);
2988               } /* if */
2989             } /* if */
2990             break;
2991           case SQL_BLOB:
2992             if (sqlvar->sqlsubtype == 1) {
2993               /* BLOB SUB_TYPE 1 means essentially: textual Blob. */
2994               columnValue = getClob(preparedStmt,
2995                                     (ISC_QUAD *) sqlvar->sqldata,
2996                                     &err_info);
2997             } else {
2998               /* BLOB SUB_TYPE 0 is a binary Blob. */
2999               columnValue = getBlobAsStri(preparedStmt,
3000                                           (ISC_QUAD *) sqlvar->sqldata,
3001                                           &err_info);
3002             } /* if */
3003             if (unlikely(columnValue == NULL)) {
3004               raise_error(err_info);
3005             } /* if */
3006             break;
3007 #if 0
3008           case SQL_ARRAY:
3009             length = sqlvar->sqllen;
3010             printf("length: %hd\n", length);
3011             printf("data[0]: %d\n", sqlvar->sqldata[0]);
3012             printf("data[1]: %d\n", sqlvar->sqldata[1]);
3013             printf("data[2]: %d\n", sqlvar->sqldata[2]);
3014             printf("data[3]: %d\n", sqlvar->sqldata[3]);
3015             printf("data[4]: %d\n", sqlvar->sqldata[4]);
3016             printf("data[5]: %d\n", sqlvar->sqldata[5]);
3017             printf("data[6]: %d\n", sqlvar->sqldata[6]);
3018             printf("data[7]: %d\n", sqlvar->sqldata[7]);
3019             printf("varyingLength: %u\n",
3020                    sqlvar->sqldata[0] +
3021                    sqlvar->sqldata[1] * 256);
3022             printf("sqldata: " FMT_U_MEM "\n", (memSizeType) sqlvar->sqldata);
3023             printf("varyingLength: %hu\n",
3024                    *(uint16Type *) sqlvar->sqldata);
3025             raise_error(RANGE_ERROR);
3026             columnValue = NULL;
3027             break;
3028 #endif
3029           default:
3030             logError(printf("sqlColumnStri: Column " FMT_D " has the unknown type %s.\n",
3031                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
3032             raise_error(RANGE_ERROR);
3033             columnValue = NULL;
3034             break;
3035         } /* switch */
3036       } /* if */
3037     } /* if */
3038     logFunction(printf("sqlColumnStri --> \"%s\"\n", striAsUnquotedCStri(columnValue)););
3039     return columnValue;
3040   } /* sqlColumnStri */
3041 
3042 
3043 
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)3044 static void sqlColumnTime (sqlStmtType sqlStatement, intType column,
3045     intType *year, intType *month, intType *day, intType *hour,
3046     intType *minute, intType *second, intType *micro_second,
3047     intType *time_zone, boolType *is_dst)
3048 
3049   {
3050     preparedStmtType preparedStmt;
3051     XSQLVAR *sqlvar;
3052     short *sqlind;
3053     struct tm tm_time;
3054 
3055   /* sqlColumnTime */
3056     logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ")\n",
3057                        (memSizeType) sqlStatement, column););
3058     preparedStmt = (preparedStmtType) sqlStatement;
3059     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3060                  column > preparedStmt->out_sqlda->sqld)) {
3061       logError(printf("sqlColumnTime: Fetch okay: %d, column: " FMT_D
3062                       ", max column: %hd.\n",
3063                       preparedStmt->fetchOkay, column,
3064                       preparedStmt->out_sqlda->sqld););
3065       raise_error(RANGE_ERROR);
3066     } else {
3067       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
3068       sqlind = sqlvar->sqlind;
3069       if (sqlind != NULL && *sqlind == -1) {
3070         /* printf("Column is NULL -> Use default value: 0-01-01 00:00:00\n"); */
3071         *year         = 0;
3072         *month        = 1;
3073         *day          = 1;
3074         *hour         = 0;
3075         *minute       = 0;
3076         *second       = 0;
3077         *micro_second = 0;
3078         *time_zone    = 0;
3079         *is_dst       = 0;
3080       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
3081         dbInconsistent("sqlColumnTime", "sqlind");
3082         logError(printf("sqlColumnTime: Column " FMT_D ": "
3083                         "sqlind has the value %d.\n",
3084                         column, *sqlind););
3085         raise_error(DATABASE_ERROR);
3086       } else {
3087         /* printf("columnType: %s\n", nameOfSqlType(sqlvar->sqltype & ~1)); */
3088         switch (sqlvar->sqltype & ~1) {
3089           case SQL_TIMESTAMP:
3090             isc_decode_timestamp((ISC_TIMESTAMP *) sqlvar->sqldata, &tm_time);
3091             *year   = tm_time.tm_year + 1900;
3092             *month  = tm_time.tm_mon + 1;
3093             *day    = tm_time.tm_mday;
3094             *hour   = tm_time.tm_hour;
3095             *minute = tm_time.tm_min;
3096             *second = tm_time.tm_sec;
3097             *micro_second = (intType) (((ISC_TIMESTAMP *) sqlvar->sqldata)->timestamp_time % 10000) * 100;
3098             timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
3099                           time_zone, is_dst);
3100             break;
3101           case SQL_TYPE_TIME:
3102             isc_decode_sql_time((ISC_TIME *) sqlvar->sqldata, &tm_time);
3103             *year   = tm_time.tm_year + 1900;
3104             *month  = tm_time.tm_mon + 1;
3105             *day    = tm_time.tm_mday;
3106             *hour   = tm_time.tm_hour;
3107             *minute = tm_time.tm_min;
3108             *second = tm_time.tm_sec;
3109             *micro_second = (intType) (*(ISC_TIME *) sqlvar->sqldata % 10000) * 100;
3110             timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
3111                           time_zone, is_dst);
3112             break;
3113           case SQL_TYPE_DATE:
3114             isc_decode_sql_date((ISC_DATE *) sqlvar->sqldata, &tm_time);
3115             *year   = tm_time.tm_year + 1900;
3116             *month  = tm_time.tm_mon + 1;
3117             *day    = tm_time.tm_mday;
3118             *hour   = tm_time.tm_hour;
3119             *minute = tm_time.tm_min;
3120             *second = tm_time.tm_sec;
3121             *micro_second = 0;
3122             timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
3123                           time_zone, is_dst);
3124             break;
3125           default:
3126             logError(printf("sqlColumnTime: Column " FMT_D " has the unknown type %s.\n",
3127                             column, nameOfSqlType(sqlvar->sqltype & ~1)););
3128             raise_error(RANGE_ERROR);
3129             break;
3130         } /* switch */
3131       } /* if */
3132     } /* if */
3133     logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", "
3134                                         F_D(04) "-" F_D(02) "-" F_D(02) " "
3135                                         F_D(02) ":" F_D(02) ":" F_D(02) "."
3136                                         F_D(06) ", " FMT_D ", %d) -->\n",
3137                        (memSizeType) sqlStatement, column,
3138                        *year, *month, *day, *hour, *minute, *second,
3139                        *micro_second, *time_zone, *is_dst););
3140   } /* sqlColumnTime */
3141 
3142 
3143 
sqlCommit(databaseType database)3144 static void sqlCommit (databaseType database)
3145 
3146   {
3147     dbType db;
3148     ISC_STATUS status_vector[20];
3149 
3150   /* sqlCommit */
3151     logFunction(printf("sqlCommit(" FMT_U_MEM ")\n",
3152                        (memSizeType) database););
3153     db = (dbType) database;
3154     isc_commit_transaction(status_vector,
3155                            &db->trans_handle);
3156     if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
3157       setDbErrorMsg("sqlCommit", "isc_commit_transaction",
3158                     status_vector);
3159       logError(printf("sqlCommit: isc_commit_transaction error:\n%s\n",
3160                       dbError.message););
3161       raise_error(DATABASE_ERROR);
3162     } else {
3163       /* Set transaction handle to zero for isc_start_transaction(). */
3164       db->trans_handle = 0;
3165       isc_start_transaction(status_vector,
3166                             &db->trans_handle,
3167                             1,
3168                             &db->connection,
3169                             (unsigned short) sizeof(isc_tbp),
3170                             isc_tbp);
3171       if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
3172         setDbErrorMsg("sqlCommit", "isc_start_transaction",
3173                       status_vector);
3174         logError(printf("sqlCommit: isc_start_transaction error:\n%s\n",
3175                         dbError.message););
3176         raise_error(DATABASE_ERROR);
3177       } /* if */
3178     } /* if */
3179   } /* sqlCommit */
3180 
3181 
3182 
sqlExecute(sqlStmtType sqlStatement)3183 static void sqlExecute (sqlStmtType sqlStatement)
3184 
3185   {
3186     preparedStmtType preparedStmt;
3187     ISC_STATUS status_vector[20];
3188     errInfoType err_info = OKAY_NO_ERROR;
3189 
3190   /* sqlExecute */
3191     logFunction(printf("sqlExecute(" FMT_U_MEM ")\n",
3192                        (memSizeType) sqlStatement););
3193     preparedStmt = (preparedStmtType) sqlStatement;
3194     if (unlikely(!allParametersBound(preparedStmt))) {
3195       dbLibError("sqlExecute", "SQLExecute",
3196                  "Unbound statement parameter(s).\n");
3197       raise_error(DATABASE_ERROR);
3198     } else {
3199       /* printf("ppStmt: " FMT_U_MEM "\n", (memSizeType) preparedStmt->ppStmt); */
3200       if (preparedStmt->executeSuccessful) {
3201         if (unlikely((isc_dsql_free_statement(status_vector,
3202                                               &preparedStmt->ppStmt,
3203                                               DSQL_close),
3204                       status_vector[0] == 1 && status_vector[1] != 0))) {
3205           setDbErrorMsg("sqlExecute", "isc_dsql_free_statement",
3206                         status_vector);
3207           logError(printf("sqlExecute: isc_dsql_free_statement error:\n%s\n",
3208                           dbError.message););
3209           err_info = DATABASE_ERROR;
3210         } else {
3211           preparedStmt->executeSuccessful = FALSE;
3212         } /* if */
3213       } /* if */
3214       if (unlikely(err_info != OKAY_NO_ERROR)) {
3215         raise_error(err_info);
3216       } else {
3217         preparedStmt->fetchOkay = FALSE;
3218         isc_dsql_execute2(status_vector,
3219                           &preparedStmt->db->trans_handle,
3220                           &preparedStmt->ppStmt,
3221                           1, /* in_sqlda uses an XSQLDA descriptor. */
3222                           preparedStmt->in_sqlda,
3223                           NULL); /* Multiple rows are accessed with isc_dsql_fetch(). */
3224         if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
3225           setDbErrorMsg("sqlExecute", "isc_dsql_execute2",
3226                         status_vector);
3227           logError(printf("sqlExecute: isc_dsql_execute2:\n%s\n",
3228                           dbError.message););
3229           preparedStmt->executeSuccessful = FALSE;
3230           raise_error(DATABASE_ERROR);
3231         } else {
3232           if (preparedStmt->statement_type == isc_info_sql_stmt_ddl) {
3233             sqlCommit((databaseType) preparedStmt->db);
3234           } /* if */
3235           preparedStmt->executeSuccessful = TRUE;
3236           preparedStmt->fetchFinished = FALSE;
3237         } /* if */
3238       } /* if */
3239     } /* if */
3240     logFunction(printf("sqlExecute -->\n"););
3241   } /* sqlExecute */
3242 
3243 
3244 
sqlFetch(sqlStmtType sqlStatement)3245 static boolType sqlFetch (sqlStmtType sqlStatement)
3246 
3247   {
3248     preparedStmtType preparedStmt;
3249     ISC_STATUS status_vector[20];
3250     ISC_STATUS fetch_result;
3251 
3252   /* sqlFetch */
3253     logFunction(printf("sqlFetch(" FMT_U_MEM ")\n",
3254                        (memSizeType) sqlStatement););
3255     preparedStmt = (preparedStmtType) sqlStatement;
3256     if (unlikely(!preparedStmt->executeSuccessful)) {
3257       dbLibError("sqlFetch", "SQLExecute",
3258                  "Execute was not successful.\n");
3259       logError(printf("sqlFetch: Execute was not successful.\n"););
3260       preparedStmt->fetchOkay = FALSE;
3261       raise_error(DATABASE_ERROR);
3262     } else if (preparedStmt->out_sqlda->sqld == 0) {
3263       preparedStmt->fetchOkay = FALSE;
3264     } else if (!preparedStmt->fetchFinished) {
3265       /* printf("ppStmt: " FMT_U_MEM "\n", (memSizeType) preparedStmt->ppStmt); */
3266       fetch_result = isc_dsql_fetch(status_vector,
3267                                     &preparedStmt->ppStmt,
3268                                     1, /* out_sqlda uses an XSQLDA descriptor. */
3269                                     preparedStmt->out_sqlda);
3270       if (fetch_result == 0) {
3271         /* printf("fetch success\n"); */
3272         preparedStmt->fetchOkay = TRUE;
3273       } else if (fetch_result == 100) {
3274         preparedStmt->fetchOkay = FALSE;
3275         preparedStmt->fetchFinished = TRUE;
3276       } else {
3277         setDbErrorMsg("sqlFetch", "isc_dsql_fetch",
3278                       status_vector);
3279         logError(printf("sqlFetch: isc_dsql_fetch fetch_result: " FMT_D_MEM ":\n%s\n",
3280                         (memSizeType) fetch_result, dbError.message););
3281         preparedStmt->fetchOkay = FALSE;
3282         preparedStmt->fetchFinished = TRUE;
3283         raise_error(DATABASE_ERROR);
3284       } /* if */
3285     } /* if */
3286     logFunction(printf("sqlFetch --> %d\n", preparedStmt->fetchOkay););
3287     return preparedStmt->fetchOkay;
3288   } /* sqlFetch */
3289 
3290 
3291 
sqlIsNull(sqlStmtType sqlStatement,intType column)3292 static boolType sqlIsNull (sqlStmtType sqlStatement, intType column)
3293 
3294   {
3295     preparedStmtType preparedStmt;
3296     XSQLVAR *sqlvar;
3297     short *sqlind;
3298     boolType isNull;
3299 
3300   /* sqlIsNull */
3301     logFunction(printf("sqlIsNull(" FMT_U_MEM ", " FMT_D ")\n",
3302                        (memSizeType) sqlStatement, column););
3303     preparedStmt = (preparedStmtType) sqlStatement;
3304     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3305                  column > preparedStmt->out_sqlda->sqld)) {
3306       logError(printf("sqlIsNull: Fetch okay: %d, column: " FMT_D
3307                       ", max column: %hd.\n",
3308                       preparedStmt->fetchOkay, column,
3309                       preparedStmt->out_sqlda->sqld););
3310       raise_error(RANGE_ERROR);
3311       isNull = FALSE;
3312     } else {
3313       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
3314       sqlind = sqlvar->sqlind;
3315       if (sqlind != NULL && *sqlind == -1) {
3316         isNull = TRUE;
3317       } else if (unlikely(sqlind != NULL && *sqlind != 0)) {
3318         dbInconsistent("sqlColumnInt", "sqlind");
3319         logError(printf("sqlColumnInt: Column " FMT_D ": "
3320                         "sqlind has the value %d.\n",
3321                         column, *sqlind););
3322         raise_error(DATABASE_ERROR);
3323         isNull = FALSE;
3324       } else {
3325         isNull = FALSE;
3326       } /* if */
3327     } /* if */
3328     logFunction(printf("sqlIsNull --> %s\n", isNull ? "TRUE" : "FALSE"););
3329     return isNull;
3330   } /* sqlIsNull */
3331 
3332 
3333 
sqlPrepare(databaseType database,const const_striType sqlStatementStri)3334 static sqlStmtType sqlPrepare (databaseType database,
3335     const const_striType sqlStatementStri)
3336 
3337   {
3338     dbType db;
3339     cstriType query;
3340     memSizeType queryLength;
3341     XSQLDA *out_sqlda;
3342     ISC_STATUS status_vector[20];
3343     char res_buffer[8];
3344     short length;
3345     errInfoType err_info = OKAY_NO_ERROR;
3346     preparedStmtType preparedStmt;
3347 
3348   /* sqlPrepare */
3349     logFunction(printf("sqlPrepare(" FMT_U_MEM ", \"%s\")\n",
3350                        (memSizeType) database,
3351                        striAsUnquotedCStri(sqlStatementStri)););
3352     db = (dbType) database;
3353     if (db->connection == 0) {
3354       logError(printf("sqlPrepare: Database is not open.\n"););
3355       err_info = RANGE_ERROR;
3356       preparedStmt = NULL;
3357     } else {
3358       query = stri_to_cstri8_buf(sqlStatementStri, &queryLength);
3359       if (unlikely(query == NULL)) {
3360         err_info = MEMORY_ERROR;
3361         preparedStmt = NULL;
3362       } else {
3363         if (unlikely(queryLength > UINT16TYPE_MAX)) {
3364           /* It is not possible to cast queryLength to unsigned short. */
3365           logError(printf("sqlPrepare: Statement string too long (length = " FMT_U_MEM ")\n",
3366                           queryLength););
3367           err_info = RANGE_ERROR;
3368           preparedStmt = NULL;
3369         } else if (unlikely((out_sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(1))) == NULL ||
3370                             !ALLOC_RECORD2(preparedStmt, preparedStmtRecord,
3371                                            count.prepared_stmt, count.prepared_stmt_bytes))) {
3372           if (out_sqlda != NULL) {
3373             free(out_sqlda);
3374           } /* if */
3375           err_info = MEMORY_ERROR;
3376           preparedStmt = NULL;
3377         } else {
3378           /* printf("sqlPrepare: query: %s\n", query); */
3379           memset(out_sqlda, 0, XSQLDA_LENGTH(1));
3380           memset(preparedStmt, 0, sizeof(preparedStmtRecord));
3381           out_sqlda->version = SQLDA_VERSION1;
3382           out_sqlda->sqln = 1;
3383           /* The statement handle must be zero when isc_dsql_allocate_statement() is called. */
3384           preparedStmt->ppStmt = 0;
3385           if ((isc_dsql_allocate_statement(status_vector,
3386                                            &db->connection,
3387                                            &preparedStmt->ppStmt),
3388                status_vector[0] == 1 && status_vector[1] != 0)) {
3389             setDbErrorMsg("sqlPrepare", "isc_dsql_allocate_statement",
3390                           status_vector);
3391             logError(printf("sqlPrepare(" FMT_U_MEM ", \"%s\"): "
3392                             "isc_dsql_allocate_statement error:\n%s\n",
3393                             (memSizeType) database,
3394                             striAsUnquotedCStri(sqlStatementStri),
3395                             dbError.message););
3396             free(out_sqlda);
3397             err_info = DATABASE_ERROR;
3398           } else if ((isc_dsql_prepare(status_vector,
3399                                        &db->trans_handle,
3400                                        &preparedStmt->ppStmt,
3401                                        (unsigned short) queryLength,
3402                                        query,
3403                                        3, /* dialect, indicates V6.0 functionalities */
3404                                        out_sqlda),
3405                       status_vector[0] == 1 && status_vector[1] != 0)) {
3406             setDbErrorMsg("sqlPrepare", "isc_dsql_prepare",
3407                           status_vector);
3408             logError(printf("sqlPrepare(" FMT_U_MEM ", \"%s\"): "
3409                             "isc_dsql_prepare error:\n%s\n",
3410                             (memSizeType) database,
3411                             striAsUnquotedCStri(sqlStatementStri),
3412                             dbError.message););
3413             free(out_sqlda);
3414             err_info = DATABASE_ERROR;
3415           } else {
3416             preparedStmt->usage_count = 1;
3417             preparedStmt->sqlFunc = db->sqlFunc;
3418             preparedStmt->executeSuccessful = FALSE;
3419             preparedStmt->fetchOkay = FALSE;
3420             preparedStmt->fetchFinished = TRUE;
3421             preparedStmt->db = db;
3422             err_info = setupParameters(preparedStmt);
3423             if (unlikely(err_info != OKAY_NO_ERROR)) {
3424               free(out_sqlda);
3425             } else {
3426               err_info = setupResult(preparedStmt, out_sqlda);
3427               if (likely(err_info == OKAY_NO_ERROR)) {
3428                 isc_dsql_sql_info(status_vector,
3429                                   &preparedStmt->ppStmt,
3430                                   sizeof(type_item),
3431                                   type_item,
3432                                   sizeof(res_buffer),
3433                                   res_buffer);
3434                 if (unlikely(status_vector[0] == 1 && status_vector[1] != 0)) {
3435                   setDbErrorMsg("sqlPrepare", "isc_dsql_sql_info",
3436                                 status_vector);
3437                   logError(printf("sqlPrepare: isc_dsql_sql_info:\n%s\n",
3438                                  dbError.message););
3439                 } else {
3440                   if (res_buffer[0] == isc_info_sql_stmt_type) {
3441                     length = (short) isc_portable_integer(&res_buffer[1], 2);
3442                     preparedStmt->statement_type =
3443                         (int) isc_portable_integer(&res_buffer[3], length);
3444                     /* printf("statement_type: %d\n", preparedStmt->statement_type); */
3445                   } /* if */
3446                 } /* if */
3447               } /* if */
3448             } /* if */
3449           } /* if */
3450           if (unlikely(err_info != OKAY_NO_ERROR)) {
3451             freePreparedStmt((sqlStmtType) preparedStmt);
3452             preparedStmt = NULL;
3453           } /* if */
3454         } /* if */
3455         free_cstri8(query, sqlStatementStri);
3456       } /* if */
3457     } /* if */
3458     if (unlikely(err_info != OKAY_NO_ERROR)) {
3459       raise_error(err_info);
3460     } /* if */
3461     logFunction(printf("sqlPrepare --> " FMT_U_MEM "\n",
3462                        (memSizeType) preparedStmt););
3463     return (sqlStmtType) preparedStmt;
3464   } /* sqlPrepare */
3465 
3466 
3467 
sqlStmtColumnCount(sqlStmtType sqlStatement)3468 static intType sqlStmtColumnCount (sqlStmtType sqlStatement)
3469 
3470   {
3471     preparedStmtType preparedStmt;
3472     intType columnCount;
3473 
3474   /* sqlStmtColumnCount */
3475     logFunction(printf("sqlStmtColumnCount(" FMT_U_MEM ")\n",
3476                        (memSizeType) sqlStatement););
3477     preparedStmt = (preparedStmtType) sqlStatement;
3478     /* The element sqld has the type ISC_SHORT (short).      */
3479     /* Therefore it will always fit into the intType result. */
3480     columnCount = (intType) preparedStmt->out_sqlda->sqld;
3481     logFunction(printf("sqlStmtColumnCount --> " FMT_D "\n", columnCount););
3482     return columnCount;
3483   } /* sqlStmtColumnCount */
3484 
3485 
3486 
sqlStmtColumnName(sqlStmtType sqlStatement,intType column)3487 static striType sqlStmtColumnName (sqlStmtType sqlStatement, intType column)
3488 
3489   {
3490     preparedStmtType preparedStmt;
3491     XSQLVAR *sqlvar;
3492     errInfoType err_info = OKAY_NO_ERROR;
3493     striType name;
3494 
3495   /* sqlStmtColumnName */
3496     logFunction(printf("sqlStmtColumnName(" FMT_U_MEM ", " FMT_D ")\n",
3497                        (memSizeType) sqlStatement, column););
3498     preparedStmt = (preparedStmtType) sqlStatement;
3499     if (unlikely(column < 1 ||
3500                  column > preparedStmt->out_sqlda->sqld)) {
3501       logError(printf("sqlStmtColumnName: column: " FMT_D
3502                       ", max column: %hd.\n",
3503                       column, preparedStmt->out_sqlda->sqld););
3504       raise_error(RANGE_ERROR);
3505       name = NULL;
3506     } else {
3507       sqlvar = &preparedStmt->out_sqlda->sqlvar[column - 1];
3508       if (unlikely(sqlvar->sqlname_length < 0)) {
3509         dbInconsistent("sqlStmtColumnName", "length");
3510         logError(printf("sqlStmtColumnName: Column " FMT_D ": "
3511                         "sqlname_length %hd is negative.\n", column,
3512                         sqlvar->sqlname_length););
3513         raise_error(DATABASE_ERROR);
3514         name = NULL;
3515       } else {
3516         name = cstri8_buf_to_stri(sqlvar->sqlname,
3517             (memSizeType) sqlvar->sqlname_length, &err_info);
3518         if (unlikely(name == NULL)) {
3519           raise_error(err_info);
3520         } /* if */
3521       } /* if */
3522     } /* if */
3523     logFunction(printf("sqlStmtColumnName --> \"%s\"\n",
3524                        striAsUnquotedCStri(name)););
3525     return name;
3526   } /* sqlStmtColumnName */
3527 
3528 
3529 
setupFuncTable(void)3530 static boolType setupFuncTable (void)
3531 
3532   { /* setupFuncTable */
3533     if (sqlFunc == NULL) {
3534       if (ALLOC_RECORD(sqlFunc, sqlFuncRecord, count.sql_func)) {
3535         memset(sqlFunc, 0, sizeof(sqlFuncRecord));
3536         sqlFunc->freeDatabase       = &freeDatabase;
3537         sqlFunc->freePreparedStmt   = &freePreparedStmt;
3538         sqlFunc->sqlBindBigInt      = &sqlBindBigInt;
3539         sqlFunc->sqlBindBigRat      = &sqlBindBigRat;
3540         sqlFunc->sqlBindBool        = &sqlBindBool;
3541         sqlFunc->sqlBindBStri       = &sqlBindBStri;
3542         sqlFunc->sqlBindDuration    = &sqlBindDuration;
3543         sqlFunc->sqlBindFloat       = &sqlBindFloat;
3544         sqlFunc->sqlBindInt         = &sqlBindInt;
3545         sqlFunc->sqlBindNull        = &sqlBindNull;
3546         sqlFunc->sqlBindStri        = &sqlBindStri;
3547         sqlFunc->sqlBindTime        = &sqlBindTime;
3548         sqlFunc->sqlClose           = &sqlClose;
3549         sqlFunc->sqlColumnBigInt    = &sqlColumnBigInt;
3550         sqlFunc->sqlColumnBigRat    = &sqlColumnBigRat;
3551         sqlFunc->sqlColumnBool      = &sqlColumnBool;
3552         sqlFunc->sqlColumnBStri     = &sqlColumnBStri;
3553         sqlFunc->sqlColumnDuration  = &sqlColumnDuration;
3554         sqlFunc->sqlColumnFloat     = &sqlColumnFloat;
3555         sqlFunc->sqlColumnInt       = &sqlColumnInt;
3556         sqlFunc->sqlColumnStri      = &sqlColumnStri;
3557         sqlFunc->sqlColumnTime      = &sqlColumnTime;
3558         sqlFunc->sqlCommit          = &sqlCommit;
3559         sqlFunc->sqlExecute         = &sqlExecute;
3560         sqlFunc->sqlFetch           = &sqlFetch;
3561         sqlFunc->sqlIsNull          = &sqlIsNull;
3562         sqlFunc->sqlPrepare         = &sqlPrepare;
3563         sqlFunc->sqlStmtColumnCount = &sqlStmtColumnCount;
3564         sqlFunc->sqlStmtColumnName  = &sqlStmtColumnName;
3565       } /* if */
3566     } /* if */
3567     return sqlFunc != NULL;
3568   } /* setupFuncTable */
3569 
3570 
3571 
doAttach(loginType loginData,const_cstriType extension,isc_db_handle * db_handle)3572 static errInfoType doAttach (loginType loginData, const_cstriType extension,
3573     isc_db_handle *db_handle)
3574 
3575   {
3576     const const_cstriType charset = "UTF8";
3577     memSizeType charset_length;
3578     memSizeType extension_length;
3579     memSizeType fileName8Length;
3580     cstriType fileName8;
3581     memSizeType dpb_buffer_length;
3582     char *dpb_buffer;
3583     short dpb_length;
3584     char *dpb;
3585     ISC_STATUS status_vector[20];
3586     errInfoType err_info = OKAY_NO_ERROR;
3587 
3588   /* doAttach */
3589     extension_length = strlen(extension);
3590     if (loginData->fileName8Length < extension_length ||
3591         memcmp(&loginData->fileName8[loginData->fileName8Length - extension_length],
3592                extension, extension_length) != 0) {
3593       fileName8Length = loginData->fileName8Length + extension_length;
3594       if (unlikely(fileName8Length > 255 ||
3595                    !ALLOC_CSTRI(fileName8, fileName8Length))) {
3596         err_info = MEMORY_ERROR;
3597       } else {
3598         memcpy(fileName8, loginData->fileName8, loginData->fileName8Length);
3599         memcpy(&fileName8[loginData->fileName8Length], extension, extension_length);
3600         fileName8[fileName8Length] = '\0';
3601       } /* if */
3602     } else {
3603       fileName8Length = loginData->fileName8Length;
3604       fileName8 = loginData->fileName8;
3605     } /* if */
3606     if (likely(err_info == OKAY_NO_ERROR)) {
3607       charset_length = strlen(charset);
3608       /* Assume that the setting bytes take less then 256 bytes space. */
3609       dpb_buffer_length = fileName8Length + loginData->user8Length +
3610           loginData->password8Length + charset_length + 256;
3611       if (unlikely(!ALLOC_CSTRI(dpb_buffer, dpb_buffer_length))) {
3612         err_info = MEMORY_ERROR;
3613       } else {
3614         /* Construct the database parameter buffer. */
3615         dpb = dpb_buffer;
3616         *dpb++ = isc_dpb_version1;
3617         *dpb++ = isc_dpb_utf8_filename;
3618         *dpb++ = (char) fileName8Length;
3619         memcpy(dpb, fileName8, fileName8Length);
3620         dpb += fileName8Length;
3621         *dpb++ = isc_dpb_user_name;
3622         *dpb++ = (char) loginData->user8Length;
3623         memcpy(dpb, loginData->user8, loginData->user8Length);
3624         dpb += loginData->user8Length;
3625         *dpb++ = isc_dpb_password;
3626         *dpb++ = (char) loginData->password8Length;
3627         memcpy(dpb, loginData->password8, loginData->password8Length);
3628         dpb += loginData->password8Length;
3629         *dpb++ = isc_dpb_set_db_charset;
3630         *dpb++ = (char) charset_length;
3631         memcpy(dpb, charset, charset_length);
3632         dpb += charset_length;
3633 #if 0
3634         /* what does this? */
3635         *dpb++ = isc_num_buffers;
3636         *dpb++ = 1;
3637         *dpb++ = 90;
3638 #endif
3639         /* Add (unnecessary) null byte, to be on the safe side. */
3640         *dpb = '\0';
3641         dpb_length = (short) (dpb - dpb_buffer);
3642         /* Set database handle to zero before attaching to a database. */
3643         *db_handle = 0;
3644         /* Attach to the database. */
3645         isc_attach_database(status_vector, (short) fileName8Length,
3646                             fileName8, db_handle, dpb_length, dpb_buffer);
3647         if (status_vector[0] == 1 && status_vector[1] != 0) {
3648           setDbErrorMsg("sqlOpenFire", "isc_attach_database",
3649                         status_vector);
3650           logError(printf("sqlOpenFire: isc_attach_database(*, \"%s\", ...  )"
3651                           " user: \"%s\", password: \"%s\", error:\n%s\n",
3652                           fileName8, loginData->user8, loginData->password8,
3653                           dbError.message););
3654           err_info = DATABASE_ERROR;
3655         } /* if */
3656         UNALLOC_CSTRI(dpb_buffer, dpb_buffer_length);
3657       } /* if */
3658       if (fileName8 != loginData->fileName8) {
3659         UNALLOC_CSTRI(fileName8, fileName8Length);
3660       } /* if */
3661     } /* if */
3662     return err_info;
3663   } /* doAttach */
3664 
3665 
3666 
sqlOpenFire(const const_striType host,intType port,const const_striType dbName,const const_striType user,const const_striType password)3667 databaseType sqlOpenFire (const const_striType host, intType port,
3668     const const_striType dbName, const const_striType user,
3669     const const_striType password)
3670 
3671   {
3672     striType fileName;
3673     const const_cstriType extensions[] = {".fdb", ".gdb", ""};
3674     unsigned int idx;
3675     loginRecord loginData;
3676     isc_db_handle db_handle;
3677     isc_tr_handle trans_handle = 0; /* Set to zero for isc_start_transaction(). */
3678     ISC_STATUS status_vector[20];
3679     errInfoType err_info = OKAY_NO_ERROR;
3680     dbType database;
3681 
3682   /* sqlOpenFire */
3683     logFunction(printf("sqlOpenFire(\"%s\", ",
3684                        striAsUnquotedCStri(host));
3685                 printf(FMT_D ", \"%s\", ",
3686                        port, striAsUnquotedCStri(dbName));
3687                 printf("\"%s\", ", striAsUnquotedCStri(user));
3688                 printf("\"%s\")\n", striAsUnquotedCStri(password)););
3689     if (!findDll()) {
3690       logError(printf("sqlOpenFire: findDll() failed\n"););
3691       err_info = DATABASE_ERROR;
3692       database = NULL;
3693     } else {
3694       fileName = cmdToOsPath(dbName);
3695       if (fileName == NULL) {
3696         database = NULL;
3697       } else {
3698         loginData.fileName8 = stri_to_cstri8_buf(fileName, &loginData.fileName8Length);
3699         if (unlikely(loginData.fileName8 == NULL)) {
3700           err_info = MEMORY_ERROR;
3701           database = NULL;
3702         } else {
3703           loginData.user8 = stri_to_cstri8_buf(user, &loginData.user8Length);
3704           if (unlikely(loginData.user8 == NULL)) {
3705             err_info = MEMORY_ERROR;
3706             database = NULL;
3707           } else {
3708             loginData.password8 = stri_to_cstri8_buf(password, &loginData.password8Length);
3709             if (unlikely(loginData.password8 == NULL)) {
3710               err_info = MEMORY_ERROR;
3711               database = NULL;
3712             } else {
3713               if (loginData.fileName8Length > 255 || loginData.user8Length > 255 ||
3714                   loginData.password8Length > 255) {
3715                 logError(printf("sqlOpenFire: File name, user or password too long.\n"););
3716                 err_info = RANGE_ERROR;
3717                 database = NULL;
3718               } else {
3719                 idx = 0;
3720                 do {
3721                   err_info = doAttach(&loginData, extensions[idx], &db_handle);
3722                   idx++;
3723                 } while (err_info == DATABASE_ERROR &&
3724                          idx < sizeof(extensions) / sizeof(cstriType));
3725                 if (unlikely(err_info != OKAY_NO_ERROR)) {
3726                   database = NULL;
3727                 } else {
3728                   if ((isc_start_transaction(status_vector,
3729                                              &trans_handle,
3730                                              1,
3731                                              &db_handle,
3732                                              (unsigned short) sizeof(isc_tbp),
3733                                              isc_tbp),
3734                               status_vector[0] == 1 && status_vector[1] != 0)) {
3735                     setDbErrorMsg("sqlOpenFire", "isc_start_transaction",
3736                                   status_vector);
3737                     logError(printf("sqlOpenFire: isc_start_transaction error:\n%s\n",
3738                                     dbError.message););
3739                     err_info = DATABASE_ERROR;
3740                     isc_detach_database(status_vector, &db_handle);
3741                     database = NULL;
3742                   } else if (unlikely(!setupFuncTable() ||
3743                                       !ALLOC_RECORD2(database, dbRecord,
3744                                                      count.database, count.database_bytes))) {
3745                     err_info = MEMORY_ERROR;
3746                     isc_rollback_transaction(status_vector, &trans_handle);
3747                     isc_detach_database(status_vector, &db_handle);
3748                     database = NULL;
3749                   } else {
3750                     memset(database, 0, sizeof(dbRecord));
3751                     database->usage_count = 1;
3752                     database->sqlFunc = sqlFunc;
3753                     database->driver = DB_CATEGORY_FIREBIRD;
3754                     database->connection = db_handle;
3755                     database->trans_handle = trans_handle;
3756                   } /* if */
3757                 } /* if */
3758               } /* if */
3759               free_cstri8(loginData.password8, password);
3760             } /* if */
3761             free_cstri8(loginData.user8, user);
3762           } /* if */
3763           free_cstri8(loginData.fileName8, fileName);
3764         } /* if */
3765         strDestr(fileName);
3766       } /* if */
3767     } /* if */
3768     if (unlikely(err_info != OKAY_NO_ERROR)) {
3769       raise_error(err_info);
3770     } /* if */
3771     logFunction(printf("sqlOpenFire --> " FMT_U_MEM "\n",
3772                        (memSizeType) database););
3773     return (databaseType) database;
3774   } /* sqlOpenFire */
3775 
3776 #else
3777 
3778 
3779 
sqlOpenFire(const const_striType host,intType port,const const_striType dbName,const const_striType user,const const_striType password)3780 databaseType sqlOpenFire (const const_striType host, intType port,
3781     const const_striType dbName, const const_striType user,
3782     const const_striType password)
3783 
3784   { /* sqlOpenFire */
3785     logError(printf("sqlOpenFire(\"%s\", ",
3786                     striAsUnquotedCStri(host));
3787              printf(FMT_D ", \"%s\", ",
3788                     port, striAsUnquotedCStri(dbName));
3789              printf("\"%s\", ", striAsUnquotedCStri(user));
3790              printf("\"%s\"): Firebird/InterBase driver not present.\n",
3791                     striAsUnquotedCStri(password)););
3792     raise_error(RANGE_ERROR);
3793     return NULL;
3794   } /* sqlOpenFire */
3795 
3796 #endif
3797