1 /********************************************************************/
2 /*                                                                  */
3 /*  sql_oci.c     Database access functions for OCI.                */
4 /*  Copyright (C) 1989 - 2020  Thomas Mertes                        */
5 /*                                                                  */
6 /*  This file is part of the Seed7 Runtime Library.                 */
7 /*                                                                  */
8 /*  The Seed7 Runtime Library is free software; you can             */
9 /*  redistribute it and/or modify it under the terms of the GNU     */
10 /*  Lesser General Public License as published by the Free Software */
11 /*  Foundation; either version 2.1 of the License, or (at your      */
12 /*  option) any later version.                                      */
13 /*                                                                  */
14 /*  The Seed7 Runtime Library is distributed in the hope that it    */
15 /*  will be useful, but WITHOUT ANY WARRANTY; without even the      */
16 /*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /*  PURPOSE.  See the GNU Lesser General Public License for more    */
18 /*  details.                                                        */
19 /*                                                                  */
20 /*  You should have received a copy of the GNU Lesser General       */
21 /*  Public License along with this program; if not, write to the    */
22 /*  Free Software Foundation, Inc., 51 Franklin Street,             */
23 /*  Fifth Floor, Boston, MA  02110-1301, USA.                       */
24 /*                                                                  */
25 /*  Module: Seed7 Runtime Library                                   */
26 /*  File: seed7/src/sql_oci.c                                       */
27 /*  Changes: 2013, 2014, 2015, 2017 - 2020  Thomas Mertes           */
28 /*  Content: Database access functions for OCI.                     */
29 /*                                                                  */
30 /********************************************************************/
31 
32 #define LOG_FUNCTIONS 0
33 #define VERBOSE_EXCEPTIONS 0
34 
35 #include "version.h"
36 
37 #include "stdlib.h"
38 #include "stdio.h"
39 #include "string.h"
40 #include "time.h"
41 #include "math.h"
42 #include "float.h"
43 #include "limits.h"
44 #ifdef OCI_INCLUDE
45 #include OCI_INCLUDE
46 #endif
47 
48 #include "common.h"
49 #include "data_rtl.h"
50 #include "striutl.h"
51 #include "heaputl.h"
52 #include "numutl.h"
53 #include "int_rtl.h"
54 #include "flt_rtl.h"
55 #include "str_rtl.h"
56 #include "tim_rtl.h"
57 #include "cmd_rtl.h"
58 #include "big_drv.h"
59 #include "rtl_err.h"
60 #include "dll_drv.h"
61 #include "sql_base.h"
62 #include "sql_drv.h"
63 
64 #ifdef OCI_INCLUDE
65 
66 
67 typedef struct {
68     uintType     usage_count;
69     sqlFuncType  sqlFunc;
70     intType      driver;
71     OCIEnv      *oci_environment;
72     OCIServer   *oci_server;
73     OCIError    *oci_error;
74     OCISession  *oci_session;
75     OCISvcCtx   *oci_service_context;
76     ub2          charSetId;
77     boolType     autoCommit;
78   } dbRecord, *dbType;
79 
80 typedef struct {
81     OCIBind     *bind_handle;
82     uint16Type   buffer_type;
83     memSizeType  buffer_length;
84     memSizeType  buffer_capacity;
85     void        *buffer;
86     void        *descriptor;
87     int16Type    indicator;
88     boolType     bound;
89   } bindDataRecord, *bindDataType;
90 
91 typedef struct {
92     OCIParam    *column_handle;
93     OCIDefine   *define_handle;
94     uint16Type   buffer_type;
95     memSizeType  buffer_length;
96     void        *buffer;
97     uint16Type   length;
98     memSizeType  long_data_buf_usage;
99     uint32Type   long_data_piece_size;
100     uint16Type   return_code;
101     void        *descriptor;
102     OCIRef      *ref;
103     int16Type    indicator;
104   } resultDataRecord, *resultDataType;
105 
106 typedef struct {
107     uintType       usage_count;
108     sqlFuncType    sqlFunc;
109     dbType         db;
110     OCIEnv        *oci_environment;
111     OCIError      *oci_error;
112     OCISvcCtx     *oci_service_context;
113     ub2            charSetId;
114     OCIStmt       *ppStmt;
115     uint16Type     statementType;
116     memSizeType    param_array_size;
117     bindDataType   param_array;
118     memSizeType    result_array_size;
119     resultDataType result_array;
120     boolType       executeSuccessful;
121     boolType       fetchOkay;
122     boolType       fetchFinished;
123   } preparedStmtRecord, *preparedStmtType;
124 
125 typedef struct {
126     memSizeType tnsNameLength;
127     cstriType tnsName;
128     memSizeType connectStringServiceLength;
129     cstriType connectStringService;
130     memSizeType connectStringSidLength;
131     cstriType connectStringSid;
132   } connectDataRecord, *connectDataType;
133 
134 static sqlFuncType sqlFunc = NULL;
135 
136 #define DEFAULT_PORT 1521
137 #define CONNECT_STRING_SERVICE_TEMPLATE "(DESCRIPTION=(ADDRESS_LIST=" \
138             "(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=%s)))" \
139             "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=%s)))"
140 #define CONNECT_STRING_SID_TEMPLATE "(DESCRIPTION=(ADDRESS_LIST=" \
141             "(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=%s)))" \
142             "(CONNECT_DATA=(SERVER=DEDICATED)(SID=%s)))"
143 #define MAX_BIND_VAR_SIZE 4
144 #define MIN_BIND_VAR_NUM 0
145 #define MAX_BIND_VAR_NUM (26 * 26 * 26 - 1)
146 #define SIZEOF_SQLT_NUM 22
147 #define SIZEOF_SQLT_TIMESTAMP_TZ 13
148 #define MANTISSA_LEN 40
149 #define LONG_DATA_BUFFER_SIZE_INCREMENT 4096
150 #define ERROR_MESSAGE_BUFFER_SIZE 1024
151 
152 #define SET_NUMBER_TO_POSITIVE_INFINITY(buffer, length) \
153         length = 2; \
154         ((unsigned char *) (buffer))[0] = 255; \
155         ((unsigned char *) (buffer))[1] = 101;
156 
157 #define SET_NUMBER_TO_NEGATIVE_INFINITY(buffer, length) \
158         length = 1; \
159         ((unsigned char *) (buffer))[0] = 0;
160 
161 /* Not a Number (NaN), defined by this driver. */
162 #define SET_NUMBER_TO_NAN(buffer, length) \
163         length = 1; \
164         ((unsigned char *) (buffer))[0] = 255;
165 
166 
167 #ifdef OCI_DLL
168 typedef sword (*tp_OCIAttrGet) (const void *trgthndlp, ub4 trghndltyp,
169                                 void *attributep, ub4 *sizep, ub4 attrtype,
170                                 OCIError *errhp);
171 typedef sword (*tp_OCIAttrSet) (void *trgthndlp, ub4 trghndltyp, void *attributep,
172                                 ub4 size, ub4 attrtype, OCIError *errhp);
173 typedef sword (*tp_OCIBindByPos) (OCIStmt *stmtp, OCIBind **bindp, OCIError *errhp,
174                                   ub4 position, void *valuep, sb4 value_sz,
175                                   ub2 dty, void *indp, ub2 *alenp, ub2 *rcodep,
176                                   ub4 maxarr_len, ub4 *curelep, ub4 mode);
177 typedef sword (*tp_OCIDateTimeConstruct) (void *hndl,OCIError *err,OCIDateTime *datetime,
178                                           sb2 yr,ub1 mnth,ub1 dy,ub1 hr,ub1 mm,ub1 ss,ub4 fsec,
179                                           OraText *timezone, size_t timezone_length);
180 typedef sword (*tp_OCIDateTimeGetDate) (void *hndl, OCIError *err,  const OCIDateTime *date,
181                                         sb2 *yr, ub1 *mnth, ub1 *dy);
182 typedef sword (*tp_OCIDateTimeGetTime) (void *hndl, OCIError *err, OCIDateTime *datetime,
183                                         ub1 *hr, ub1 *mm, ub1 *ss, ub4 *fsec);
184 typedef sword (*tp_OCIDateTimeGetTimeZoneOffset) (void *hndl, OCIError *err,
185                                                   OCIDateTime *datetime, sb1 *hour, sb1 *min);
186 typedef sword (*tp_OCIDefineByPos) (OCIStmt *stmtp, OCIDefine **defnp, OCIError *errhp,
187                                     ub4 position, void *valuep, sb4 value_sz, ub2 dty,
188                                     void *indp, ub2 *rlenp, ub2 *rcodep, ub4 mode);
189 typedef sword (*tp_OCIDefineDynamic) (OCIDefine *defnp, OCIError *errhp, void *octxp,
190                                       OCICallbackDefine ocbfp);
191 typedef sword (*tp_OCIDefineObject) (OCIDefine *defnp, OCIError *errhp,
192                                      const OCIType *type, void **pgvpp,
193                                      ub4 *pvszsp, void **indpp, ub4 *indszp);
194 typedef sword (*tp_OCIDescriptorAlloc) (const void *parenth, void **descpp,
195                                         const ub4 type, const size_t xtramem_sz,
196                                         void **usrmempp);
197 typedef sword (*tp_OCIDescriptorFree) (void *descp, const ub4 type);
198 typedef sword (*tp_OCIEnvCreate) (OCIEnv **envp, ub4 mode, void *ctxp,
199                                   void *(*malocfp)(void *ctxp, size_t size),
200                                   void *(*ralocfp)(void *ctxp, void *memptr, size_t newsize),
201                                   void   (*mfreefp)(void *ctxp, void *memptr),
202                                   size_t xtramem_sz, void **usrmempp);
203 typedef sword (*tp_OCIEnvNlsCreate) (OCIEnv **envp, ub4 mode, void *ctxp,
204                                      void *(*malocfp)(void *ctxp, size_t size),
205                                      void *(*ralocfp)(void *ctxp, void *memptr, size_t newsize),
206                                      void   (*mfreefp)(void *ctxp, void *memptr),
207                                      size_t xtramem_sz, void **usrmempp,
208                                      ub2 charset, ub2 ncharset);
209 typedef sword (*tp_OCIErrorGet) (void *hndlp, ub4 recordno, OraText *sqlstate,
210                                  sb4 *errcodep, OraText *bufp, ub4 bufsiz, ub4 type);
211 typedef sword (*tp_OCIHandleAlloc) (const void *parenth, void **hndlpp, const ub4 type,
212                                     const size_t xtramem_sz, void **usrmempp);
213 typedef sword (*tp_OCIHandleFree) (void *hndlp, const ub4 type);
214 typedef sword (*tp_OCIIntervalSetDaySecond) (void *hndl, OCIError *err, sb4 dy, sb4 hr,
215                                              sb4 mm, sb4 ss, sb4 fsec, OCIInterval *result);
216 typedef sword (*tp_OCIIntervalSetYearMonth) (void *hndl, OCIError *err, sb4 yr, sb4 mnth,
217                                              OCIInterval *result);
218 typedef sword (*tp_OCIIntervalGetDaySecond) (void *hndl, OCIError *err, sb4 *dy, sb4 *hr,
219                                              sb4 *mm, sb4 *ss, sb4 *fsec, const OCIInterval *result);
220 typedef sword (*tp_OCIIntervalGetYearMonth) (void *hndl, OCIError *err, sb4 *yr, sb4 *mnth,
221                                              const OCIInterval *result);
222 typedef sword (*tp_OCILobCreateTemporary) (OCISvcCtx *svchp,
223                                            OCIError *errhp,
224                                            OCILobLocator *locp,
225                                            ub2 csid,
226                                            ub1 csfrm,
227                                            ub1 lobtype,
228                                            boolean cache,
229                                            OCIDuration duration);
230 typedef sword (*tp_OCILobFreeTemporary) (OCISvcCtx *svchp,
231                                          OCIError *errhp,
232                                          OCILobLocator *locp);
233 typedef sword (*tp_OCILobGetLength2) (OCISvcCtx *svchp, OCIError *errhp,
234                                       OCILobLocator *locp, oraub8 *lenp);
235 typedef sword (*tp_OCILobIsTemporary) (OCIEnv *envp,
236                                        OCIError *errhp,
237                                        OCILobLocator *locp,
238                                        boolean *is_temporary);
239 typedef sword (*tp_OCILobRead2) (OCISvcCtx *svchp, OCIError *errhp, OCILobLocator *locp,
240                                  oraub8 *byte_amtp, oraub8 *char_amtp, oraub8 offset,
241                                  void *bufp, oraub8 bufl, ub1 piece, void *ctxp,
242                                  OCICallbackLobRead2 cbfp, ub2 csid, ub1 csfrm);
243 typedef sword (*tp_OCILobTrim2) (OCISvcCtx *svchp, OCIError *errhp, OCILobLocator *locp,
244                                  oraub8 newlen);
245 typedef sword (*tp_OCILobWrite2) (OCISvcCtx *svchp, OCIError *errhp, OCILobLocator *locp,
246                                   oraub8 *byte_amtp, oraub8 *char_amtp, oraub8 offset,
247                                   void *bufp, oraub8 buflen, ub1 piece, void *ctxp,
248                                   OCICallbackLobWrite2 cbfp, ub2 csid, ub1 csfrm);
249 typedef ub2 (*tp_OCINlsCharSetNameToId) (void *envhp, const oratext *name);
250 typedef sword (*tp_OCINumberToReal) (OCIError *err, const OCINumber *number,
251                                      uword rsl_length, void *rsl);
252 typedef sword (*tp_OCIParamGet) (const void *hndlp, ub4 htype, OCIError *errhp,
253                                  void **parmdpp, ub4 pos);
254 typedef ub4 (*tp_OCIRefHexSize) (OCIEnv *env, const OCIRef *ref);
255 typedef sword (*tp_OCIRefToHex) (OCIEnv *env, OCIError *err, const OCIRef *ref,
256                                  oratext *hex, ub4 *hex_length);
257 typedef sword (*tp_OCIRowidToChar) (OCIRowid *rowidDesc, OraText *outbfp, ub2 *outbflp,
258                                     OCIError *errhp);
259 typedef sword (*tp_OCIServerAttach) (OCIServer *srvhp, OCIError *errhp,
260                                      const OraText *dblink, sb4 dblink_len, ub4 mode);
261 typedef sword (*tp_OCIServerDetach) (OCIServer *srvhp, OCIError *errhp, ub4 mode);
262 typedef sword (*tp_OCISessionBegin) (OCISvcCtx *svchp, OCIError *errhp, OCISession *usrhp,
263                                      ub4 credt, ub4 mode);
264 typedef sword (*tp_OCISessionEnd) (OCISvcCtx *svchp, OCIError *errhp, OCISession *usrhp,
265                                    ub4 mode);
266 typedef sword (*tp_OCIStmtExecute) (OCISvcCtx *svchp, OCIStmt *stmtp, OCIError *errhp,
267                                     ub4 iters, ub4 rowoff, const OCISnapshot *snap_in,
268                                     OCISnapshot *snap_out, ub4 mode);
269 typedef sword (*tp_OCIStmtFetch2) (OCIStmt *stmtp, OCIError *errhp, ub4 nrows,
270                                    ub2 orientation, sb4 scrollOffset, ub4 mode);
271 typedef sword (*tp_OCIStmtPrepare) (OCIStmt *stmtp, OCIError *errhp, const OraText *stmt,
272                                     ub4 stmt_len, ub4 language, ub4 mode);
273 typedef oratext *(*tp_OCIStringPtr) (OCIEnv *env, const OCIString *vs);
274 typedef ub4 (*tp_OCIStringSize) (OCIEnv *env, const OCIString *vs);
275 typedef sword (*tp_OCITransCommit) (OCISvcCtx *svchp, OCIError *errhp, ub4 flags);
276 typedef sword (*tp_OCITransRollback) (dvoid *svchp,  OCIError *errhp, ub4 flags);
277 
278 static tp_OCIAttrGet                   ptr_OCIAttrGet;
279 static tp_OCIAttrSet                   ptr_OCIAttrSet;
280 static tp_OCIBindByPos                 ptr_OCIBindByPos;
281 static tp_OCIDateTimeConstruct         ptr_OCIDateTimeConstruct;
282 static tp_OCIDateTimeGetDate           ptr_OCIDateTimeGetDate;
283 static tp_OCIDateTimeGetTime           ptr_OCIDateTimeGetTime;
284 static tp_OCIDateTimeGetTimeZoneOffset ptr_OCIDateTimeGetTimeZoneOffset;
285 static tp_OCIDefineByPos               ptr_OCIDefineByPos;
286 static tp_OCIDefineDynamic             ptr_OCIDefineDynamic;
287 static tp_OCIDefineObject              ptr_OCIDefineObject;
288 static tp_OCIDescriptorAlloc           ptr_OCIDescriptorAlloc;
289 static tp_OCIDescriptorFree            ptr_OCIDescriptorFree;
290 static tp_OCIEnvCreate                 ptr_OCIEnvCreate;
291 static tp_OCIEnvNlsCreate              ptr_OCIEnvNlsCreate;
292 static tp_OCIErrorGet                  ptr_OCIErrorGet;
293 static tp_OCIHandleAlloc               ptr_OCIHandleAlloc;
294 static tp_OCIHandleFree                ptr_OCIHandleFree;
295 static tp_OCIIntervalSetDaySecond      ptr_OCIIntervalSetDaySecond;
296 static tp_OCIIntervalSetYearMonth      ptr_OCIIntervalSetYearMonth;
297 static tp_OCIIntervalGetDaySecond      ptr_OCIIntervalGetDaySecond;
298 static tp_OCIIntervalGetYearMonth      ptr_OCIIntervalGetYearMonth;
299 static tp_OCILobCreateTemporary        ptr_OCILobCreateTemporary;
300 static tp_OCILobFreeTemporary          ptr_OCILobFreeTemporary;
301 static tp_OCILobGetLength2             ptr_OCILobGetLength2;
302 static tp_OCILobIsTemporary            ptr_OCILobIsTemporary;
303 static tp_OCILobRead2                  ptr_OCILobRead2;
304 static tp_OCILobTrim2                  ptr_OCILobTrim2;
305 static tp_OCILobWrite2                 ptr_OCILobWrite2;
306 static tp_OCINlsCharSetNameToId        ptr_OCINlsCharSetNameToId;
307 static tp_OCINumberToReal              ptr_OCINumberToReal;
308 static tp_OCIParamGet                  ptr_OCIParamGet;
309 static tp_OCIRefHexSize                ptr_OCIRefHexSize;
310 static tp_OCIRefToHex                  ptr_OCIRefToHex;
311 static tp_OCIRowidToChar               ptr_OCIRowidToChar;
312 static tp_OCIServerAttach              ptr_OCIServerAttach;
313 static tp_OCIServerDetach              ptr_OCIServerDetach;
314 static tp_OCISessionBegin              ptr_OCISessionBegin;
315 static tp_OCISessionEnd                ptr_OCISessionEnd;
316 static tp_OCIStmtExecute               ptr_OCIStmtExecute;
317 static tp_OCIStmtFetch2                ptr_OCIStmtFetch2;
318 static tp_OCIStmtPrepare               ptr_OCIStmtPrepare;
319 static tp_OCIStringPtr                 ptr_OCIStringPtr;
320 static tp_OCIStringSize                ptr_OCIStringSize;
321 static tp_OCITransCommit               ptr_OCITransCommit;
322 static tp_OCITransRollback             ptr_OCITransRollback;
323 
324 #define OCIAttrGet                   ptr_OCIAttrGet
325 #define OCIAttrSet                   ptr_OCIAttrSet
326 #define OCIBindByPos                 ptr_OCIBindByPos
327 #define OCIDateTimeConstruct         ptr_OCIDateTimeConstruct
328 #define OCIDateTimeGetDate           ptr_OCIDateTimeGetDate
329 #define OCIDateTimeGetTime           ptr_OCIDateTimeGetTime
330 #define OCIDateTimeGetTimeZoneOffset ptr_OCIDateTimeGetTimeZoneOffset
331 #define OCIDefineByPos               ptr_OCIDefineByPos
332 #define OCIDefineDynamic             ptr_OCIDefineDynamic
333 #define OCIDefineObject              ptr_OCIDefineObject
334 #define OCIDescriptorAlloc           ptr_OCIDescriptorAlloc
335 #define OCIDescriptorFree            ptr_OCIDescriptorFree
336 #define OCIEnvCreate                 ptr_OCIEnvCreate
337 #define OCIEnvNlsCreate              ptr_OCIEnvNlsCreate
338 #define OCIErrorGet                  ptr_OCIErrorGet
339 #define OCIHandleAlloc               ptr_OCIHandleAlloc
340 #define OCIHandleFree                ptr_OCIHandleFree
341 #define OCIIntervalSetDaySecond      ptr_OCIIntervalSetDaySecond
342 #define OCIIntervalSetYearMonth      ptr_OCIIntervalSetYearMonth
343 #define OCIIntervalGetDaySecond      ptr_OCIIntervalGetDaySecond
344 #define OCIIntervalGetYearMonth      ptr_OCIIntervalGetYearMonth
345 #define OCILobCreateTemporary        ptr_OCILobCreateTemporary
346 #define OCILobFreeTemporary          ptr_OCILobFreeTemporary
347 #define OCILobGetLength2             ptr_OCILobGetLength2
348 #define OCILobIsTemporary            ptr_OCILobIsTemporary
349 #define OCILobRead2                  ptr_OCILobRead2
350 #define OCILobTrim2                  ptr_OCILobTrim2
351 #define OCILobWrite2                 ptr_OCILobWrite2
352 #define OCINlsCharSetNameToId        ptr_OCINlsCharSetNameToId
353 #define OCINumberToReal              ptr_OCINumberToReal
354 #define OCIParamGet                  ptr_OCIParamGet
355 #define OCIRefHexSize                ptr_OCIRefHexSize
356 #define OCIRefToHex                  ptr_OCIRefToHex
357 #define OCIRowidToChar               ptr_OCIRowidToChar
358 #define OCIServerAttach              ptr_OCIServerAttach
359 #define OCIServerDetach              ptr_OCIServerDetach
360 #define OCISessionBegin              ptr_OCISessionBegin
361 #define OCISessionEnd                ptr_OCISessionEnd
362 #define OCIStmtExecute               ptr_OCIStmtExecute
363 #define OCIStmtFetch2                ptr_OCIStmtFetch2
364 #define OCIStmtPrepare               ptr_OCIStmtPrepare
365 #define OCIStringPtr                 ptr_OCIStringPtr
366 #define OCIStringSize                ptr_OCIStringSize
367 #define OCITransCommit               ptr_OCITransCommit
368 #define OCITransRollback             ptr_OCITransRollback
369 
370 
371 
setupDll(const char * dllName)372 static boolType setupDll (const char *dllName)
373 
374   {
375     static void *dbDll = NULL;
376 
377   /* setupDll */
378     logFunction(printf("setupDll(\"%s\")\n", dllName););
379     if (dbDll == NULL) {
380       dbDll = dllOpen(dllName);
381       if (dbDll != NULL) {
382         if ((OCIAttrGet                   = (tp_OCIAttrGet)                   dllFunc(dbDll, "OCIAttrGet"))                   == NULL ||
383             (OCIAttrSet                   = (tp_OCIAttrSet)                   dllFunc(dbDll, "OCIAttrSet"))                   == NULL ||
384             (OCIBindByPos                 = (tp_OCIBindByPos)                 dllFunc(dbDll, "OCIBindByPos"))                 == NULL ||
385             (OCIDateTimeConstruct         = (tp_OCIDateTimeConstruct)         dllFunc(dbDll, "OCIDateTimeConstruct"))         == NULL ||
386             (OCIDateTimeGetDate           = (tp_OCIDateTimeGetDate)           dllFunc(dbDll, "OCIDateTimeGetDate"))           == NULL ||
387             (OCIDateTimeGetTime           = (tp_OCIDateTimeGetTime)           dllFunc(dbDll, "OCIDateTimeGetTime"))           == NULL ||
388             (OCIDateTimeGetTimeZoneOffset = (tp_OCIDateTimeGetTimeZoneOffset) dllFunc(dbDll, "OCIDateTimeGetTimeZoneOffset")) == NULL ||
389             (OCIDefineByPos               = (tp_OCIDefineByPos)               dllFunc(dbDll, "OCIDefineByPos"))               == NULL ||
390             (OCIDefineDynamic             = (tp_OCIDefineDynamic)             dllFunc(dbDll, "OCIDefineDynamic"))             == NULL ||
391             (OCIDefineObject              = (tp_OCIDefineObject)              dllFunc(dbDll, "OCIDefineObject"))              == NULL ||
392             (OCIDescriptorAlloc           = (tp_OCIDescriptorAlloc)           dllFunc(dbDll, "OCIDescriptorAlloc"))           == NULL ||
393             (OCIDescriptorFree            = (tp_OCIDescriptorFree)            dllFunc(dbDll, "OCIDescriptorFree"))            == NULL ||
394             (OCIEnvCreate                 = (tp_OCIEnvCreate)                 dllFunc(dbDll, "OCIEnvCreate"))                 == NULL ||
395             (OCIEnvNlsCreate              = (tp_OCIEnvNlsCreate)              dllFunc(dbDll, "OCIEnvNlsCreate"))              == NULL ||
396             (OCIErrorGet                  = (tp_OCIErrorGet)                  dllFunc(dbDll, "OCIErrorGet"))                  == NULL ||
397             (OCIHandleAlloc               = (tp_OCIHandleAlloc)               dllFunc(dbDll, "OCIHandleAlloc"))               == NULL ||
398             (OCIHandleFree                = (tp_OCIHandleFree)                dllFunc(dbDll, "OCIHandleFree"))                == NULL ||
399             (OCIIntervalSetDaySecond      = (tp_OCIIntervalSetDaySecond)      dllFunc(dbDll, "OCIIntervalSetDaySecond"))      == NULL ||
400             (OCIIntervalSetYearMonth      = (tp_OCIIntervalSetYearMonth)      dllFunc(dbDll, "OCIIntervalSetYearMonth"))      == NULL ||
401             (OCIIntervalGetDaySecond      = (tp_OCIIntervalGetDaySecond)      dllFunc(dbDll, "OCIIntervalGetDaySecond"))      == NULL ||
402             (OCIIntervalGetYearMonth      = (tp_OCIIntervalGetYearMonth)      dllFunc(dbDll, "OCIIntervalGetYearMonth"))      == NULL ||
403             (OCILobCreateTemporary        = (tp_OCILobCreateTemporary)        dllFunc(dbDll, "OCILobCreateTemporary"))        == NULL ||
404             (OCILobFreeTemporary          = (tp_OCILobFreeTemporary)          dllFunc(dbDll, "OCILobFreeTemporary"))          == NULL ||
405             (OCILobGetLength2             = (tp_OCILobGetLength2)             dllFunc(dbDll, "OCILobGetLength2"))             == NULL ||
406             (OCILobIsTemporary            = (tp_OCILobIsTemporary)            dllFunc(dbDll, "OCILobIsTemporary"))            == NULL ||
407             (OCILobRead2                  = (tp_OCILobRead2)                  dllFunc(dbDll, "OCILobRead2"))                  == NULL ||
408             (OCILobTrim2                  = (tp_OCILobTrim2)                  dllFunc(dbDll, "OCILobTrim2"))                  == NULL ||
409             (OCILobWrite2                 = (tp_OCILobWrite2)                 dllFunc(dbDll, "OCILobWrite2"))                 == NULL ||
410             (OCINlsCharSetNameToId        = (tp_OCINlsCharSetNameToId)        dllFunc(dbDll, "OCINlsCharSetNameToId"))        == NULL ||
411             (OCINumberToReal              = (tp_OCINumberToReal)              dllFunc(dbDll, "OCINumberToReal"))              == NULL ||
412             (OCIParamGet                  = (tp_OCIParamGet)                  dllFunc(dbDll, "OCIParamGet"))                  == NULL ||
413             (OCIRefHexSize                = (tp_OCIRefHexSize)                dllFunc(dbDll, "OCIRefHexSize"))                == NULL ||
414             (OCIRefToHex                  = (tp_OCIRefToHex)                  dllFunc(dbDll, "OCIRefToHex"))                  == NULL ||
415             (OCIRowidToChar               = (tp_OCIRowidToChar)               dllFunc(dbDll, "OCIRowidToChar"))               == NULL ||
416             (OCIServerAttach              = (tp_OCIServerAttach)              dllFunc(dbDll, "OCIServerAttach"))              == NULL ||
417             (OCIServerDetach              = (tp_OCIServerDetach)              dllFunc(dbDll, "OCIServerDetach"))              == NULL ||
418             (OCISessionBegin              = (tp_OCISessionBegin)              dllFunc(dbDll, "OCISessionBegin"))              == NULL ||
419             (OCISessionEnd                = (tp_OCISessionEnd)                dllFunc(dbDll, "OCISessionEnd"))                == NULL ||
420             (OCIStmtExecute               = (tp_OCIStmtExecute)               dllFunc(dbDll, "OCIStmtExecute"))               == NULL ||
421             (OCIStmtFetch2                = (tp_OCIStmtFetch2)                dllFunc(dbDll, "OCIStmtFetch2"))                == NULL ||
422             (OCIStmtPrepare               = (tp_OCIStmtPrepare)               dllFunc(dbDll, "OCIStmtPrepare"))               == NULL ||
423             (OCIStringPtr                 = (tp_OCIStringPtr)                 dllFunc(dbDll, "OCIStringPtr"))                 == NULL ||
424             (OCIStringSize                = (tp_OCIStringSize)                dllFunc(dbDll, "OCIStringSize"))                == NULL ||
425             (OCITransCommit               = (tp_OCITransCommit)               dllFunc(dbDll, "OCITransCommit"))               == NULL ||
426             (OCITransRollback             = (tp_OCITransRollback)             dllFunc(dbDll, "OCITransRollback"))             == NULL) {
427           dbDll = NULL;
428         } /* if */
429       } /* if */
430     } /* if */
431     logFunction(printf("setupDll --> %d\n", dbDll != NULL););
432     return dbDll != NULL;
433   } /* setupDll */
434 
435 
436 
findDll(void)437 static boolType findDll (void)
438 
439   {
440     const char *dllList[] = { OCI_DLL };
441     unsigned int pos;
442     boolType found = FALSE;
443 
444   /* findDll */
445     for (pos = 0; pos < sizeof(dllList) / sizeof(char *) && !found; pos++) {
446       found = setupDll(dllList[pos]);
447     } /* for */
448     if (!found) {
449       dllErrorMessage("sqlOpenOci", "findDll", dllList,
450                       sizeof(dllList) / sizeof(char *));
451     } /* if */
452     return found;
453   } /* findDll */
454 
455 #else
456 
457 #define findDll() TRUE
458 
459 #endif
460 
461 
462 
463 static void sqlClose (databaseType database);
464 
465 
466 
467 #if VERBOSE_EXCEPTIONS || VERBOSE_EXCEPTIONS_EVERYWHERE
printError(OCIError * oci_error)468 static void printError (OCIError *oci_error)
469 
470   {
471     sb4 errcode;
472     char messageText[ERROR_MESSAGE_BUFFER_SIZE];
473 
474   /* printError */
475     if (OCIErrorGet(oci_error, 1, NULL, &errcode, (OraText *) messageText,
476                     ERROR_MESSAGE_BUFFER_SIZE, OCI_HTYPE_ERROR) != OCI_SUCCESS) {
477       printf(" *** Failed to get error description.\n");
478     } else {
479       printf("errcode: " FMT_D32 "\n", errcode);
480       printf("%s\n", messageText);
481     } /* if */
482   } /* printError */
483 #endif
484 
485 
486 
setDbErrorMsg(const char * funcName,const char * dbFuncName,OCIError * oci_error)487 static void setDbErrorMsg (const char *funcName, const char *dbFuncName,
488     OCIError *oci_error)
489 
490   {
491     sb4 errCode;
492 
493   /* setDbErrorMsg */
494     dbError.funcName = funcName;
495     dbError.dbFuncName = dbFuncName;
496     if (OCIErrorGet(oci_error, 1, NULL, &errCode,
497                     (OraText *) dbError.message,
498                     DB_ERR_MESSAGE_SIZE, OCI_HTYPE_ERROR) != OCI_SUCCESS) {
499       dbError.errorCode = 0;
500       snprintf(dbError.message, DB_ERR_MESSAGE_SIZE,
501                " *** Failed to get error description.");
502     } else {
503       dbError.errorCode = errCode;
504     } /* if */
505   } /* setDbErrorMsg */
506 
507 
508 
509 /**
510  *  Closes a database and frees the memory used by it.
511  */
freeDatabase(databaseType database)512 static void freeDatabase (databaseType database)
513 
514   {
515     dbType db;
516 
517   /* freeDatabase */
518     logFunction(printf("freeDatabase(" FMT_U_MEM ")\n",
519                        (memSizeType) database););
520     sqlClose(database);
521     db = (dbType) database;
522     FREE_RECORD2(db, dbRecord, count.database, count.database_bytes);
523     logFunction(printf("freeDatabase -->\n"););
524   } /* freeDatabase */
525 
526 
527 
freeDescriptor(preparedStmtType preparedStmt,void * descriptor,uint16Type buffer_type)528 static void freeDescriptor (preparedStmtType preparedStmt,
529     void *descriptor, uint16Type buffer_type)
530 
531   {
532     boolean is_temporary;
533 
534   /* freeDescriptor */
535     switch (buffer_type) {
536       case SQLT_RDD:
537         OCIDescriptorFree(descriptor, OCI_DTYPE_ROWID);  /* ROWID */
538         break;
539       case SQLT_BLOB:
540       case SQLT_CLOB:
541         if (unlikely(OCILobIsTemporary(preparedStmt->oci_environment,
542                                        preparedStmt->oci_error,
543                                        (OCILobLocator *) descriptor,
544                                        &is_temporary) != OCI_SUCCESS)) {
545           setDbErrorMsg("freeDescriptor", "OCILobIsTemporary",
546                         preparedStmt->oci_error);
547           logError(printf("freeDescriptor: OCILobIsTemporary:\n%s\n",
548                           dbError.message););
549           raise_error(DATABASE_ERROR);
550         } else if (is_temporary) {
551           if (unlikely(OCILobFreeTemporary(preparedStmt->oci_service_context,
552                                            preparedStmt->oci_error,
553                                            (OCILobLocator *) descriptor) != OCI_SUCCESS)) {
554             setDbErrorMsg("freeDescriptor", "OCILobFreeTemporary",
555                           preparedStmt->oci_error);
556             logError(printf("freeDescriptor: OCILobFreeTemporary:\n%s\n",
557                             dbError.message););
558             raise_error(DATABASE_ERROR);
559           } /* if */
560         } /* if */
561         OCIDescriptorFree(descriptor, OCI_DTYPE_LOB);  /* Binary LOB or Character LOB */
562         break;
563       case SQLT_FILE:
564         OCIDescriptorFree(descriptor, OCI_DTYPE_FILE);  /* Binary FILE */
565         break;
566       case SQLT_DATE:
567         OCIDescriptorFree(descriptor, OCI_DTYPE_DATE);  /* ANSI DATE */
568         break;
569       case SQLT_TIMESTAMP:
570         OCIDescriptorFree(descriptor, OCI_DTYPE_TIMESTAMP);  /* TIMESTAMP */
571         break;
572       case SQLT_TIMESTAMP_TZ:
573         OCIDescriptorFree(descriptor, OCI_DTYPE_TIMESTAMP_TZ);  /* TIMESTAMP WITH TIME ZONE */
574         break;
575       case SQLT_TIMESTAMP_LTZ:
576         OCIDescriptorFree(descriptor, OCI_DTYPE_TIMESTAMP_LTZ);  /* TIMESTAMP WITH LOCAL TIME ZONE */
577         break;
578       case SQLT_INTERVAL_YM:
579         OCIDescriptorFree(descriptor, OCI_DTYPE_INTERVAL_YM);  /* INTERVAL YEAR TO MONTH descriptor */
580         break;
581       case SQLT_INTERVAL_DS:
582         OCIDescriptorFree(descriptor, OCI_DTYPE_INTERVAL_DS);  /* INTERVAL DAY TO SECOND descriptor */
583         break;
584       default:
585         logError(printf("freeDescriptor: Unspecified buffer_type: %d\n", buffer_type););
586         break;
587     } /* switch */
588   } /* freeDescriptor */
589 
590 
591 
freeBindData(preparedStmtType preparedStmt,bindDataType bindData)592 static void freeBindData (preparedStmtType preparedStmt, bindDataType bindData)
593 
594   { /* freeBindData */
595     /* The bind handle is freed implicitly when the statement handle is deallocated. */
596     if (bindData->buffer != NULL) {
597       free(bindData->buffer);
598     } /* if */
599     if (bindData->descriptor != NULL) {
600       freeDescriptor(preparedStmt, bindData->descriptor, bindData->buffer_type);
601     } /* if */
602   } /* freeBindData */
603 
604 
605 
freeResultData(preparedStmtType preparedStmt,resultDataType resultData)606 static void freeResultData (preparedStmtType preparedStmt, resultDataType resultData)
607 
608   { /* freeResultData */
609     if (resultData->column_handle != NULL) {
610       OCIDescriptorFree(resultData->column_handle, OCI_DTYPE_PARAM);
611     } /* if */
612     /* It seems that the define_handle is implicitly freed with the statement handle. */
613     if (resultData->buffer != NULL && resultData->buffer != &resultData->descriptor) {
614       free(resultData->buffer);
615     } /* if */
616     if (resultData->descriptor != NULL) {
617       freeDescriptor(preparedStmt, resultData->descriptor, resultData->buffer_type);
618     } /* if */
619   } /* freeResultData */
620 
621 
622 
623 /**
624  *  Closes a prepared statement and frees the memory used by it.
625  */
freePreparedStmt(sqlStmtType sqlStatement)626 static void freePreparedStmt (sqlStmtType sqlStatement)
627 
628   {
629     preparedStmtType preparedStmt;
630     memSizeType pos;
631 
632   /* freePreparedStmt */
633     logFunction(printf("freePreparedStmt(" FMT_U_MEM ")\n",
634                        (memSizeType) sqlStatement););
635     preparedStmt = (preparedStmtType) sqlStatement;
636     if (preparedStmt->param_array != NULL) {
637       for (pos = 0; pos < preparedStmt->param_array_size; pos++) {
638         freeBindData(preparedStmt, &preparedStmt->param_array[pos]);
639       } /* for */
640       FREE_TABLE(preparedStmt->param_array, bindDataRecord, preparedStmt->param_array_size);
641     } /* if */
642     if (preparedStmt->result_array != NULL) {
643       for (pos = 0; pos < preparedStmt->result_array_size; pos++) {
644         freeResultData(preparedStmt, &preparedStmt->result_array[pos]);
645       } /* for */
646       FREE_TABLE(preparedStmt->result_array, resultDataRecord, preparedStmt->result_array_size);
647     } /* if */
648     OCIHandleFree(preparedStmt->ppStmt, OCI_HTYPE_STMT);
649     preparedStmt->db->usage_count--;
650     if (preparedStmt->db->usage_count == 0) {
651       /* printf("FREE " FMT_X_MEM "\n", (memSizeType) preparedStmt->db); */
652       freeDatabase((databaseType) preparedStmt->db);
653     } /* if */
654     FREE_RECORD2(preparedStmt, preparedStmtRecord,
655                  count.prepared_stmt, count.prepared_stmt_bytes);
656     logFunction(printf("freePreparedStmt -->\n"););
657   } /* freePreparedStmt */
658 
659 
660 
661 /**
662  *  Convert a SQLT_NUM number to a decimal integer.
663  *  @param dataLen Length of the OCINumber (ociNumber[0]).
664  *  @param ociNumberData Data bytes of the OCINumber (&ociNumber[1]).
665  *  @param stri Destination string for the decimal digits
666  *              (Needs a capacity of at least 127 characters).
667  *  @param err_info Unchanged if the function succeeds, and
668  *                  RANGE_ERROR if the number cannot be converted
669  *                  to a decimal integer.
670  */
sqltNumberToDecimalInt(memSizeType dataLen,const uint8Type * ociNumberData,striType stri)671 static errInfoType sqltNumberToDecimalInt (memSizeType dataLen,
672     const uint8Type *ociNumberData, striType stri)
673 
674   {
675     signed char exponent;
676     signed char mantissa[SIZEOF_SQLT_NUM]; /* Terminated by a negative number */
677     int idx;
678     int twoDigits;
679     unsigned int pos = 0;
680     errInfoType err_info = OKAY_NO_ERROR;
681 
682   /* sqltNumberToDecimalInt */
683     if (dataLen == 0) {
684       logError(printf("sqltNumberToDecimalInt: Too short\n"););
685       err_info = RANGE_ERROR;
686     } else if (dataLen == 1) {
687       if (ociNumberData[0] == 0x80) {
688         /* Zero */
689         stri->mem[pos++] = '0';
690       } else if (ociNumberData[0] == 0) {
691         logError(printf("sqltNumberToDecimalInt: Negative infinity\n"););
692         err_info = RANGE_ERROR;
693       } else if (ociNumberData[0] == 0xff) {
694         /* Not a Number (NaN), defined by this driver. */
695         logError(printf("sqltNumberToDecimalInt: Not a Number\n"););
696         err_info = RANGE_ERROR;
697       } else {
698         logError(printf("sqltNumberToDecimalInt: Unexpected format\n"););
699         err_info = RANGE_ERROR;
700       } /* if */
701     } else if (dataLen == 2) {
702       if (ociNumberData[0] == 255 && ociNumberData[1] == 101) {
703         logError(printf("sqltNumberToDecimalInt: Positive infinity\n"););
704         err_info = RANGE_ERROR;
705       } /* if */
706     } else if (dataLen > SIZEOF_SQLT_NUM) {
707       logError(printf("sqltNumberToDecimalInt: Too long\n"););
708       err_info = RANGE_ERROR;
709     } /* if */
710     if (pos == 0 && err_info == OKAY_NO_ERROR) {
711       /* Normalize exponent and mantissa */
712       if (ociNumberData[0] >= 128) {
713         /* Positive number */
714         exponent = (signed char) ((int) ociNumberData[0] - 193);  /* Range -65 to 62 */
715         for (idx = 0; idx < (int) dataLen - 1; idx++) {
716           mantissa[idx] = (signed char) (ociNumberData[idx + 1] - 1);
717         } /* for */
718         mantissa[idx] = -1;
719       } else {
720         /* Negative number */
721         exponent = (signed char) (62 - (int) ociNumberData[0]);  /* Range -65 to 62 */
722         for (idx = 0; idx < (int) dataLen - 1; idx++) {
723           mantissa[idx] = (signed char) (101 - ociNumberData[idx + 1]);
724         } /* for */
725         mantissa[idx] = -1;
726         stri->mem[pos++] = '-';
727       } /* if */
728       /* Convert exponent and mantissa to decimal integer */
729       idx = 0;
730       twoDigits = mantissa[idx];
731       if (exponent >= 0) {
732         /* integer part */
733         exponent--;
734         if (twoDigits / 10 != 0) {
735           stri->mem[pos++] = (strElemType) ('0' + twoDigits / 10);
736         } /* if */
737         stri->mem[pos++] = (strElemType) ('0' + twoDigits % 10);
738         idx++;
739         twoDigits = mantissa[idx];
740         while (exponent >= 0) {
741           exponent--;
742           if (twoDigits < 0) {
743             stri->mem[pos++] = '0';
744             stri->mem[pos++] = '0';
745           } else {
746             stri->mem[pos++] = (strElemType) ('0' + twoDigits / 10);
747             stri->mem[pos++] = (strElemType) ('0' + twoDigits % 10);
748             idx++;
749             twoDigits = mantissa[idx];
750           } /* if */
751         } /* while */
752       } else {
753         stri->mem[pos++] = '0';
754       } /* if */
755       if (exponent < -1 || twoDigits >= 0) {
756         logError(printf("sqltNumberToDecimalInt: Fractional number part present\n"););
757         err_info = RANGE_ERROR;
758       } /* if */
759     } /* if */
760     stri->size = (memSizeType) pos;
761     return err_info;
762   } /* sqltNumberToDecimalInt */
763 
764 
765 
766 /**
767  *  Convert an OCINumber to a decimal integer.
768  *  @param ociNumber OCINumber to be converted.
769  *  @param stri Destination string for the decimal digits
770  *              (Needs a capacity of at least 127 characters).
771  *  @param err_info Unchanged if the function succeeds, and
772  *                  RANGE_ERROR if the number cannot be converted
773  *                  to a decimal integer.
774  */
ociNumberToDecimalInt(const OCINumber * ociNumber,striType stri,errInfoType * err_info)775 static void ociNumberToDecimalInt (const OCINumber *ociNumber, striType stri,
776     errInfoType *err_info)
777 
778   { /* ociNumberToDecimalInt */
779     *err_info = sqltNumberToDecimalInt(ociNumber->OCINumberPart[0],
780                                        &ociNumber->OCINumberPart[1],
781                                        stri);
782   } /* ociNumberToDecimalInt */
783 
784 
785 
786 /**
787  *  Convert a SQLT_NUM number to a decimal fraction (integer + scale).
788  *  The number format can be used for normal numbers and infinity values.
789  *  This function additionally recognizes the value NaN (Not a Number).
790  *  @param dataLen Length of the OCINumber (ociNumber[0]).
791  *  @param ociNumberData Data bytes of the OCINumber (&ociNumber[1]).
792  *  @param stri Destination string for the decimal digits
793  *              (Needs a capacity of at least 127 characters).
794  *  @return the scale of the number. The scale is the number of digits
795  *          to the right (positive) or left (negative) of the decimal point.
796  *          For finite values the scale is greater or equal 0.
797  *          For positive and negative infinite values the scale is -1.
798  *  @param err_info Unchanged if the function succeeds, and
799  *                  RANGE_ERROR if the number cannot be converted
800  *                  to a decimal fraction.
801  */
sqltNumberToDecimalFraction(memSizeType dataLen,const uint8Type * ociNumberData,striType stri,errInfoType * err_info)802 static int sqltNumberToDecimalFraction (memSizeType dataLen,
803     const uint8Type *ociNumberData, striType stri, errInfoType *err_info)
804 
805   {
806     signed char exponent;
807     signed char mantissa[SIZEOF_SQLT_NUM]; /* Terminated by a negative number */
808     int idx;
809     int twoDigits;
810     unsigned int pos = 0;
811     int scale = 0;
812 
813   /* sqltNumberToDecimalFraction */
814     if (dataLen == 0) {
815       logError(printf("sqltNumberToDecimalFraction: Too short\n"););
816       *err_info = RANGE_ERROR;
817     } else if (dataLen == 1) {
818       if (ociNumberData[0] == 0x80) {
819         /* Zero */
820         stri->mem[pos++] = '0';
821       } else if (ociNumberData[0] == 0) {
822         /* Negative infinity */
823         stri->mem[pos++] = '-';
824         stri->mem[pos++] = '1';
825         scale = -1;
826       } else if (ociNumberData[0] == 0xff) {
827         /* Not a Number (NaN), defined by this driver. */
828         stri->mem[pos++] = '0';
829         scale = -1;
830       } else {
831         logError(printf("sqltNumberToDecimalFraction: Unexpected format %u\n",
832                         ociNumberData[0]););
833         *err_info = RANGE_ERROR;
834       } /* if */
835     } else if (dataLen == 2) {
836       if (ociNumberData[0] == 255 && ociNumberData[1] == 101) {
837         /* Positive infinity */
838         stri->mem[pos++] = '1';
839         scale = -1;
840       } /* if */
841     } else if (dataLen > SIZEOF_SQLT_NUM) {
842       logError(printf("sqltNumberToDecimalFraction: Too long\n"););
843       *err_info = RANGE_ERROR;
844     } /* if */
845     if (pos == 0 && *err_info == OKAY_NO_ERROR) {
846       /* Normalize exponent and mantissa */
847       if (ociNumberData[0] >= 128) {
848         /* Positive number */
849         exponent = (signed char) ((int) ociNumberData[0] - 193);  /* Range -65 to 62 */
850         for (idx = 0; idx < (int) dataLen - 1; idx++) {
851           mantissa[idx] = (signed char) (ociNumberData[idx + 1] - 1);
852         } /* for */
853         mantissa[idx] = -1;
854       } else {
855         /* Negative number */
856         exponent = (signed char) (62 - (int) ociNumberData[0]);  /* Range -65 to 62 */
857         for (idx = 0; idx < (int) dataLen - 1; idx++) {
858           mantissa[idx] = (signed char) (101 - ociNumberData[idx + 1]);
859         } /* for */
860         mantissa[idx] = -1;
861         stri->mem[pos++] = '-';
862       } /* if */
863       /* Convert exponent and mantissa to decimal integer */
864       idx = 0;
865       twoDigits = mantissa[idx];
866       if (exponent >= 0) {
867         /* integer part */
868         exponent--;
869         if (twoDigits / 10 != 0) {
870           stri->mem[pos++] = (strElemType) ('0' + twoDigits / 10);
871         } /* if */
872         stri->mem[pos++] = (strElemType) ('0' + twoDigits % 10);
873         idx++;
874         twoDigits = mantissa[idx];
875         while (exponent >= 0) {
876           exponent--;
877           if (twoDigits < 0) {
878             stri->mem[pos++] = '0';
879             stri->mem[pos++] = '0';
880           } else {
881             stri->mem[pos++] = (strElemType) ('0' + twoDigits / 10);
882             stri->mem[pos++] = (strElemType) ('0' + twoDigits % 10);
883             idx++;
884             twoDigits = mantissa[idx];
885           } /* if */
886         } /* while */
887       } else {
888         scale = 2 * (-exponent - 1);
889         if (twoDigits >= 0) {
890           if (twoDigits / 10 != 0) {
891             stri->mem[pos++] = (strElemType) ('0' + twoDigits / 10);
892           } /* if */
893           stri->mem[pos++] = (strElemType) ('0' + twoDigits % 10);
894           scale += 2;
895           idx++;
896           twoDigits = mantissa[idx];
897         } /* if */
898       } /* if */
899       /* Fractional number part */
900       while (twoDigits >= 0) {
901         stri->mem[pos++] = (strElemType) ('0' + twoDigits / 10);
902         stri->mem[pos++] = (strElemType) ('0' + twoDigits % 10);
903         scale += 2;
904         idx++;
905         twoDigits = mantissa[idx];
906       } /* while */
907       if (scale > 0 && stri->mem[pos - 1] == '0') {
908         scale--;
909         pos--;
910       } /* if */
911     } /* if */
912     stri->size = (memSizeType) pos;
913     return scale;
914   } /* sqltNumberToDecimalFraction */
915 
916 
917 
918 /**
919  *  Convert an OCINumber to a decimal fraction (integer + scale).
920  *  @param ociNumber OCINumber to be converted.
921  *  @param stri Destination string for the decimal digits
922  *              (Needs a capacity of at least 127 characters).
923  *  @return the scale of the number. The scale is the number of digits
924  *          to the right (positive) or left (negative) of the decimal point.
925  *          For finite values the scale is greater or equal 0.
926  *          For positive and negative infinite values the scale is -1.
927  *  @param err_info Unchanged if the function succeeds, and
928  *                  RANGE_ERROR if the number cannot be converted
929  *                  to a decimal fraction.
930  */
ociNumberToDecimalFraction(const OCINumber * ociNumber,striType stri,errInfoType * err_info)931 static int ociNumberToDecimalFraction (const OCINumber *ociNumber, striType stri,
932     errInfoType *err_info)
933 
934   { /* ociNumberToDecimalFraction */
935     return sqltNumberToDecimalFraction(ociNumber->OCINumberPart[0],
936                                        &ociNumber->OCINumberPart[1],
937                                        stri, err_info);
938   } /* ociNumberToDecimalFraction */
939 
940 
941 
942 /**
943  *  Convert a decimal integer and a scale to a SQLT_NUM number.
944  *  @param ociNumberData Place to which the SQLT_NUM number is written.
945  *  @param decimal String with a decimal integer (with possible - sign).
946  *  @param scale Number of digits to the right (positive) or
947  *               left (negative) of the decimal point.
948  *  @return the size of the SQLT_NUM number.
949  *  @param err_info Unchanged if the function succeeds, and
950  *                  RANGE_ERROR if the decimal integer + scale
951  *                  cannot be converted to a SQLT_NUM number.
952  */
sqltNumberFromDecimalInt(uint8Type * ociNumberData,const const_striType decimal,int scale,errInfoType * err_info)953 static int sqltNumberFromDecimalInt (uint8Type *ociNumberData,
954     const const_striType decimal, int scale, errInfoType *err_info)
955 
956   {
957     memSizeType pos = 0;
958     int negative = 0;
959     int decimalExponent;
960     char mantissa[MANTISSA_LEN + 1];
961     int startIdx = 1;
962     int idx = 1;
963     int length = 0;
964 
965   /* sqltNumberFromDecimalInt */
966     /* Read sign */
967     if (pos < decimal->size && decimal->mem[pos] == '-') {
968       pos++;
969       negative = 1;
970     } /* if */
971     if (pos < decimal->size && (decimal->mem[pos] < '0' || decimal->mem[pos] > '9')) {
972       logError(printf("sqltNumberFromDecimalInt: No digit found\n"););
973       *err_info = RANGE_ERROR;
974     } else {
975       while (pos < decimal->size && decimal->mem[pos] == '0') {
976         pos++;
977       } /* while */
978       /* Read decimal integer */
979       while (pos < decimal->size && decimal->mem[pos] >= '0' && decimal->mem[pos] <= '9' && idx <= MANTISSA_LEN) {
980         mantissa[idx] = (char) ((char) decimal->mem[pos] - '0');
981         idx++;
982         pos++;
983       } /* while */
984       while (pos < decimal->size && decimal->mem[pos] == '0') {
985         idx++;
986         pos++;
987       } /* while */
988       if (pos != decimal->size) {
989         logError(printf("sqltNumberFromDecimalInt: Mantissa too long or trailing nondigit chars found\n"););
990         *err_info = RANGE_ERROR;
991       } else {
992         decimalExponent = -scale + idx - 2;
993         if (decimalExponent % 2 == 0) {
994           if (idx <= MANTISSA_LEN || mantissa[MANTISSA_LEN] == 0) {
995             startIdx = 0;
996             mantissa[0] = 0;
997           } else {
998             logError(printf("sqltNumberFromDecimalInt: Mantissa too long\n"););
999             *err_info = RANGE_ERROR;
1000           } /* if */
1001         } /* if */
1002         if (*err_info == OKAY_NO_ERROR) {
1003           if (idx > MANTISSA_LEN + startIdx) {
1004             idx = MANTISSA_LEN + startIdx;
1005           } /* if */
1006           /* Shrink mantissa size */
1007           while (idx > startIdx && mantissa[idx - 1] == 0) {
1008             idx--;
1009           } /* while */
1010           if (idx == startIdx) {
1011             /* Zero */
1012             length = 1;
1013             ociNumberData[0] = 0x80;
1014           } else if (decimalExponent > 125) {
1015             logError(printf("sqltNumberFromDecimalInt: Overflow: decimalExponent=%d\n",
1016                             decimalExponent););
1017             *err_info = RANGE_ERROR;
1018           } else if (decimalExponent < -130) {
1019             logError(printf("sqltNumberFromDecimalInt: Underflow: decimalExponent=%d\n",
1020                             decimalExponent););
1021             *err_info = RANGE_ERROR;
1022           } else {
1023             /* Change the base from 10 to 100 */
1024             if ((idx - startIdx) % 2 == 1) {
1025               mantissa[idx++] = 0;
1026             } /* if */
1027             length = (idx - startIdx) / 2;
1028             for (idx = 0; idx < length; idx++) {
1029               mantissa[idx] = (char) (10 * mantissa[startIdx + idx * 2] + mantissa[startIdx + idx * 2 + 1]);
1030             } /* for */
1031             /* Add terminator for negative value */
1032             if (negative && length < 20) {
1033               mantissa[length++] = -1;
1034             } /* if */
1035 #if RSHIFT_DOES_SIGN_EXTEND
1036             decimalExponent >>= 1;
1037 #else
1038             if (decimalExponent < 0) {
1039               decimalExponent = ~(~decimalExponent >> 1);
1040             } else {
1041               decimalExponent >>= 1;
1042             } /* if */
1043 #endif
1044             if (negative) {
1045               ociNumberData[0] = (ub1) (62 - decimalExponent);
1046               for (idx = 0; idx < length; idx++) {
1047                 ociNumberData[idx + 1] = (ub1) (101 - mantissa[idx]);
1048               } /* for */
1049             } else {
1050               ociNumberData[0] = (ub1) (decimalExponent + 193);
1051               for (idx = 0; idx < length; idx++) {
1052                 ociNumberData[idx + 1] = (ub1) (mantissa[idx] + 1);
1053               } /* for */
1054             } /* if */
1055             length++;
1056           } /* if */
1057         } /* if */
1058       } /* if */
1059     } /* if */
1060     return length;
1061   } /* sqltNumberFromDecimalInt */
1062 
1063 
1064 
1065 /**
1066  *  Convert a decimal integer and a scale to an OCINumber.
1067  *  @param ociNumber Place to which the OCINumber is written.
1068  *  @param decimal String with a decimal integer (with possible - sign).
1069  *  @param scale Number of digits to the right (positive) or
1070  *               left (negative) of the decimal point.
1071  *  @param err_info Unchanged if the function succeeds, and
1072  *                  RANGE_ERROR if the decimal integer + scale
1073  *                  cannot be converted to a SQLT_NUM number.
1074  */
ociNumberFromDecimalInt(OCINumber * ociNumber,const const_striType decimal,int scale,errInfoType * err_info)1075 static void ociNumberFromDecimalInt (OCINumber *ociNumber, const const_striType decimal,
1076     int scale, errInfoType *err_info)
1077 
1078   { /* ociNumberFromDecimalInt */
1079     ociNumber->OCINumberPart[0] = (ub1) sqltNumberFromDecimalInt(&ociNumber->OCINumberPart[1],
1080                                                                  decimal, scale, err_info);
1081   } /* ociNumberFromDecimalInt */
1082 
1083 
1084 
dumpSqltNumber(memSizeType dataLen,const uint8Type * ociNumberData)1085 static void dumpSqltNumber (memSizeType dataLen, const uint8Type *ociNumberData)
1086 
1087   {
1088     memSizeType pos;
1089 
1090   /* dumpSqltNumber */
1091     printf("dataLen: " FMT_U_MEM ", \"", dataLen);
1092     for (pos = 0; pos < SIZEOF_SQLT_NUM; pos++) {
1093       printf("%02x", ociNumberData[pos]);
1094     } /* for */
1095     printf("\", ");
1096     if (dataLen > SIZEOF_SQLT_NUM) {
1097       dataLen = SIZEOF_SQLT_NUM;
1098     } /* if */
1099     if (ociNumberData[0] >= 128) {
1100       /* Positive number */
1101       printf("exponent: %d", (int) ociNumberData[0] - 193);  /* Range -65 to 62 */
1102       if (dataLen != 0) {
1103         printf(", (%02d", (int) ociNumberData[1] - 1);
1104         for (pos = 1; pos < dataLen - 1 && ociNumberData[pos + 1] - 1 != -1; pos++) {
1105           printf(" %02d", (int) ociNumberData[pos + 1] - 1);
1106         } /* for */
1107         printf(")");
1108       } /* if */
1109       printf(", positive");
1110     } else {
1111       /* Negative number */
1112       printf("exponent: %d", 62 - (int) ociNumberData[0]);  /* Range -65 to 62 */
1113       if (dataLen != 0) {
1114         printf(", (%02d", 101 - (int) ociNumberData[1]);
1115         for (pos = 1; pos < dataLen - 1 && 101 - (int) ociNumberData[pos + 1] != -1; pos++) {
1116           printf(" %02d", 101 - (int) ociNumberData[pos + 1]);
1117         } /* for */
1118         printf(")");
1119       } /* if */
1120       printf(", negative");
1121     } /* if */
1122   } /* dumpSqltNumber */
1123 
1124 
1125 
1126 #ifdef SHOW_DETAILS
printSqltNumber(memSizeType dataLen,const uint8Type * ociNumberData)1127 static void printSqltNumber (memSizeType dataLen, const uint8Type *ociNumberData)
1128 
1129   {
1130     union {
1131       struct striStruct striBuf;
1132       char charBuf[SIZ_STRI(127)];
1133     } striBuffer;
1134     int scale = 0;
1135     errInfoType err_info = OKAY_NO_ERROR;
1136 
1137   /* printSqltNumber */
1138 #if ALLOW_STRITYPE_SLICES
1139     striBuffer.striBuf.mem = striBuffer.striBuf.mem1;
1140 #endif
1141     scale = sqltNumberToDecimalFraction(dataLen, ociNumberData,
1142                                         &striBuffer.striBuf, &err_info);
1143     if (unlikely(err_info != OKAY_NO_ERROR)) {
1144       /* printf(" *OCINumber conversion failed*"); */
1145       dumpSqltNumber(dataLen, ociNumberData);
1146     } else if (scale == -1) {
1147       /* For positive and negative infinite values the scale is -1. */
1148       if (striBuffer.striBuf.mem[0] == '-') {
1149         printf("-Infinity");
1150       } else if (striBuffer.striBuf.mem[0] == '0') {
1151         /* Not a Number (NaN), defined by this driver. */
1152         printf("NaN");
1153       } else {
1154         printf("Infinity");
1155       } /* if */
1156     } else {
1157       /* printf(" "); */
1158       prot_stri_unquoted(&striBuffer.striBuf);
1159       if (scale != 0) {
1160         printf("E%d", -scale);
1161       } /* if */
1162     } /* if */
1163   } /* printSqltNumber */
1164 
1165 
1166 
printBuffer(uint16Type buffer_type,memSizeType length,void * buffer)1167 static void printBuffer (uint16Type buffer_type, memSizeType length, void *buffer)
1168 
1169   { /* printBuffer */
1170     switch (buffer_type) {
1171       case SQLT_INT:
1172         switch (length) {
1173           case 1:
1174             printf("%d", *(int8Type *) buffer);
1175             break;
1176           case 2:
1177             printf("%d", *(int16Type *) buffer);
1178             break;
1179           case 4:
1180             printf(FMT_D32, *(int32Type *) buffer);
1181             break;
1182           case 8:
1183             printf(FMT_D64, *(int64Type *) buffer);
1184             break;
1185         } /* switch */
1186         break;
1187       case SQLT_FLT:
1188         switch (length) {
1189           case FLOAT_SIZE / 8:
1190             printf("%f", *(float *) buffer);
1191             break;
1192           case DOUBLE_SIZE / 8:
1193             printf("%f", *(double *) buffer);
1194             break;
1195         } /* switch */
1196         break;
1197       case SQLT_CHR:
1198       case SQLT_AFC:
1199         fwrite(buffer, length, 1, stdout);
1200         break;
1201       case SQLT_NUM:
1202         printSqltNumber(length, (uint8Type *) buffer);
1203         break;
1204     } /* switch */
1205   } /* printBuffer */
1206 #endif
1207 
1208 
1209 
1210 #if LOG_FUNCTIONS_EVERYWHERE || LOG_FUNCTIONS || VERBOSE_EXCEPTIONS_EVERYWHERE || VERBOSE_EXCEPTIONS
nameOfBufferType(uint16Type buffer_type)1211 static const char *nameOfBufferType (uint16Type buffer_type)
1212 
1213   {
1214     static char buffer[50];
1215     static const char *const typeNameTable[] = {
1216       "0",           "SQLT_CHR",    "SQLT_NUM",    "SQLT_INT",    "SQLT_FLT",
1217       "SQLT_STR",    "SQLT_VNU",    "SQLT_PDN",    "SQLT_LNG",    "SQLT_VCS",
1218       "SQLT_NON",    "SQLT_RID",    "SQLT_DAT",    "13",          "14",
1219       "SQLT_VBI",    "16",          "17",          "18",          "19",
1220       "20",          "SQLT_BFLOAT", "SQLT_BDOUBLE","SQLT_BIN",    "SQLT_LBI",
1221       "25",  "26",   "27",  "28",   "29",  "30",   "31",  "32",   "33",  "34",
1222       "35",  "36",   "37",  "38",   "39",  "40",   "41",  "42",   "43",  "44",
1223       "45",  "46",   "47",  "48",   "49",  "50",   "51",  "52",   "53",  "54",
1224       "55",  "56",   "57",  "58",   "59",  "60",   "61",  "62",   "63",  "64",
1225       "65",          "66",          "67",          "SQLT_UIN",    "69",
1226       "70",  "71",   "72",  "73",   "74",  "75",   "76",  "77",   "78",  "79",
1227       "80",  "81",   "82",  "83",   "84",  "85",   "86",  "87",   "88",  "89",
1228       "90",          "SQLT_SLS",    "92",          "93",          "SQLT_LVC",
1229       "SQLT_LVB",    "SQLT_AFC",    "SQLT_AVC",    "98",          "99",
1230       "SQLT_IBFLOAT","SQLT_IBDOUBLE","SQLT_CUR",   "103",         "SQLT_RDD",
1231       "SQLT_LAB",    "SQLT_OSL",    "107",         "SQLT_NTY",    "109",
1232       "SQLT_REF",    "111",         "SQLT_CLOB",   "SQLT_BLOB",   "SQLT_FILE",
1233       "SQLT_CFILE",  "SQLT_RSET",   "117",         "118",         "119",
1234       "120",         "121",         "SQLT_NCO",    "123",         "124",
1235       "125", "126",  "127", "128",  "129", "130",  "131", "132",  "133", "134",
1236       "135", "136",  "137", "138",  "139", "140",  "141", "142",  "143", "144",
1237       "145", "146",  "147", "148",  "149", "150",  "151", "152",  "153", "154",
1238       "SQLT_VST",    "SQLT_ODT",    "157",         "158",         "159",
1239       "160", "161",  "162", "163",  "164", "165",  "166", "167",  "168", "169",
1240       "170", "171",  "172", "173",  "174", "175",  "176", "177",  "178", "179",
1241       "180",         "181",         "182",         "183",         "SQLT_DATE",
1242       "SQLT_TIME",   "SQLT_TIME_TZ","SQLT_TIMESTAMP", "SQLT_TIMESTAMP_TZ", "SQLT_INTERVAL_YM",
1243       "SQLT_INTERVAL_DS", "191",    "192",         "193",         "194",
1244       "195", "196",  "197", "198",  "199", "200",  "201", "202",  "203", "204"
1245       "205", "206",  "207", "208",  "209", "210",  "211", "212",  "213", "214",
1246       "215", "216",  "217", "218",  "219", "220",  "221", "222",  "223", "224",
1247       "225", "226",  "227", "228",  "229", "230",  "231", "SQLT_TIMESTAMP_LTZ",
1248     };
1249     const char *typeName;
1250 
1251   /* nameOfBufferType */
1252     logFunction(printf("nameOfBufferType(%d)\n", buffer_type););
1253     if (buffer_type <= 232) {
1254       typeName = typeNameTable[buffer_type];
1255     } else {
1256       sprintf(buffer, "%d", buffer_type);
1257       typeName = buffer;
1258     } /* if */
1259     logFunction(printf("nameOfBufferType --> %s\n", typeName););
1260     return typeName;
1261   } /* nameOfBufferType */
1262 #endif
1263 
1264 
1265 
1266 /**
1267  *  Process the bind variables in a statement string.
1268  *  Literals and comments are processed to avoid the misinterpretation
1269  *  of question marks (?).
1270  */
processStatementStri(const const_striType sqlStatementStri,memSizeType * numBindParameters,errInfoType * err_info)1271 static striType processStatementStri (const const_striType sqlStatementStri,
1272     memSizeType *numBindParameters, errInfoType *err_info)
1273 
1274   {
1275     memSizeType pos = 0;
1276     strElemType ch;
1277     strElemType delimiter;
1278     memSizeType destPos = 0;
1279     unsigned int varNum = MIN_BIND_VAR_NUM;
1280     striType processed;
1281 
1282   /* processStatementStri */
1283     logFunction(printf("processStatementStri(\"%s\")\n",
1284                        striAsUnquotedCStri(sqlStatementStri)););
1285     if (unlikely(sqlStatementStri->size > MAX_STRI_LEN / MAX_BIND_VAR_SIZE ||
1286                  !ALLOC_STRI_SIZE_OK(processed, sqlStatementStri->size * MAX_BIND_VAR_SIZE))) {
1287       *err_info = MEMORY_ERROR;
1288       processed = NULL;
1289     } else {
1290       while (pos < sqlStatementStri->size && *err_info == OKAY_NO_ERROR) {
1291         ch = sqlStatementStri->mem[pos];
1292         if (ch == '?') {
1293           if (varNum > MAX_BIND_VAR_NUM) {
1294             logError(printf("processStatementStri: Too many variables\n"););
1295             *err_info = RANGE_ERROR;
1296             FREE_STRI(processed, sqlStatementStri->size * MAX_BIND_VAR_SIZE);
1297             processed = NULL;
1298           } else {
1299             processed->mem[destPos++] = ':';
1300             processed->mem[destPos++] = 'a' +  varNum / (26 * 26);
1301             processed->mem[destPos++] = 'a' + (varNum /       26) % 26;
1302             processed->mem[destPos++] = 'a' +  varNum             % 26;
1303             varNum++;
1304           } /* if */
1305           pos++;
1306         } else if (ch == '\'' || ch == '"') {
1307           delimiter = ch;
1308           processed->mem[destPos++] = delimiter;
1309           pos++;
1310           while (pos < sqlStatementStri->size &&
1311               (ch = sqlStatementStri->mem[pos]) != delimiter) {
1312             processed->mem[destPos++] = ch;
1313             pos++;
1314           } /* while */
1315           if (pos < sqlStatementStri->size) {
1316             processed->mem[destPos++] = delimiter;
1317             pos++;
1318           } /* if */
1319         } else if (ch == '/') {
1320           pos++;
1321           if (pos >= sqlStatementStri->size || sqlStatementStri->mem[pos] != '*') {
1322             processed->mem[destPos++] = ch;
1323           } else {
1324             pos++;
1325             do {
1326               while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '*') {
1327                 pos++;
1328               } /* while */
1329               pos++;
1330             } while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '/');
1331             pos++;
1332             /* Replace the comment with a space. */
1333             processed->mem[destPos++] = ' ';
1334           } /* if */
1335         } else if (ch == '-') {
1336           pos++;
1337           if (pos >= sqlStatementStri->size || sqlStatementStri->mem[pos] != '-') {
1338             processed->mem[destPos++] = ch;
1339           } else {
1340             pos++;
1341             while (pos < sqlStatementStri->size && sqlStatementStri->mem[pos] != '\n') {
1342               pos++;
1343             } /* while */
1344             /* The final newline replaces the comment. */
1345           } /* if */
1346         } else {
1347           processed->mem[destPos++] = ch;
1348           pos++;
1349         } /* if */
1350       } /* while */
1351       processed->size = destPos;
1352     } /* if */
1353     *numBindParameters = varNum - MIN_BIND_VAR_NUM;
1354     logFunction(printf("processStatementStri --> \"%s\"\n",
1355                        striAsUnquotedCStri(processed)););
1356     return processed;
1357   } /* processStatementStri */
1358 
1359 
1360 
longCallback(dvoid * octxp,OCIDefine * define_handle,ub4 iter,dvoid ** bufpp,ub4 ** alenp,ub1 * piecep,dvoid ** indp,ub2 ** rcodep)1361 static sb4 longCallback (dvoid *octxp, OCIDefine *define_handle, ub4 iter,
1362     dvoid **bufpp, ub4 **alenp, ub1 *piecep, dvoid **indp, ub2 **rcodep)
1363 
1364   {
1365     resultDataType resultData;
1366 
1367   /* longCallback */
1368     resultData = (resultDataType) octxp;
1369 #if 0
1370     printf("iter: %u\n", iter);
1371     printf("longCallback: Field: %s, ind: %d, len %u, buf_len: " FMT_U_MEM "\n",
1372            nameOfBufferType(resultData->buffer_type),
1373            resultData->indicator,
1374            resultData->length,
1375            resultData->buffer_length);
1376     if (bufpp == NULL) {
1377       printf("IN bufp: NULL\n");
1378     } else if (*bufpp == NULL) {
1379       printf("IN bufp: *NULL*\n");
1380     } else {
1381       printf("IN bufp: " FMT_U_MEM "\n", (memSizeType) *bufpp);
1382     } /* if */
1383     if (alenp == NULL) {
1384       printf("IN alen: NULL\n");
1385     } else if (*alenp == NULL) {
1386       printf("IN alen: *NULL*\n");
1387     } else {
1388       printf("IN alen: " FMT_U_MEM "\n", (memSizeType) **alenp);
1389     } /* if */
1390     if (piecep == NULL) {
1391       printf("IN piecep: NULL\n");
1392     } else if (*piecep == OCI_ONE_PIECE) {
1393       printf("IN piecep: OCI_ONE_PIECE\n");
1394     } else if (*piecep == OCI_FIRST_PIECE) {
1395       printf("IN piecep: OCI_FIRST_PIECE\n");
1396     } else if (*piecep == OCI_NEXT_PIECE) {
1397       printf("IN piecep: OCI_NEXT_PIECE\n");
1398     } else {
1399       printf("IN piecep: %u\n", *piecep);
1400     } /* if */
1401     if (indp == NULL) {
1402       printf("IN ind: NULL\n");
1403     } else if (*indp == NULL) {
1404       printf("IN ind: *NULL*\n");
1405     } else {
1406       printf("IN ind: %lu\n", *(unsigned long *) *indp);
1407     } /* if */
1408     printf("buffer: " FMT_U_MEM "\n", (memSizeType) resultData->buffer);
1409     fwrite(resultData->buffer, 1, resultData->long_data_buf_usage, stdout);
1410     printf("\n");
1411     printf("long_data_buf_usage: " FMT_U_MEM "\n", resultData->long_data_buf_usage);
1412 #endif
1413     switch (*piecep) {
1414       case OCI_ONE_PIECE:
1415         /* OCI_ONE_PIECE */
1416         resultData->long_data_buf_usage = 0;
1417         break;
1418       case OCI_FIRST_PIECE:
1419         /* OCI_ONE_PIECE or OCI_FIRST_PIECE */
1420         resultData->long_data_buf_usage = 0;
1421         *piecep = OCI_FIRST_PIECE;
1422         break;
1423       case OCI_NEXT_PIECE:
1424         /* OCI_NEXT_PIECE or OCI_LAST_PIECE */
1425         *piecep = OCI_NEXT_PIECE;
1426         break;
1427     } /* switch */
1428     if (resultData->buffer_length > resultData->long_data_buf_usage) {
1429       resultData->long_data_piece_size = (uint32Type)
1430           (resultData->buffer_length - resultData->long_data_buf_usage);
1431       *bufpp = &((char *) resultData->buffer)[resultData->long_data_buf_usage];
1432       resultData->long_data_buf_usage = resultData->buffer_length;
1433     } else if (resultData->buffer_length == resultData->long_data_buf_usage) {
1434       resultData->buffer_length += LONG_DATA_BUFFER_SIZE_INCREMENT;
1435       resultData->buffer = realloc(resultData->buffer, resultData->buffer_length);
1436       if (resultData->buffer != NULL) {
1437         resultData->long_data_piece_size = (uint32Type)
1438             (resultData->buffer_length - resultData->long_data_buf_usage);
1439         *bufpp = &((char *) resultData->buffer)[resultData->long_data_buf_usage];
1440         resultData->long_data_buf_usage = resultData->buffer_length;
1441       } else {
1442         resultData->long_data_piece_size = 0;
1443         *piecep = OCI_LAST_PIECE;
1444       } /* if */
1445     } /* if */
1446     *alenp = &resultData->long_data_piece_size;
1447     *indp = &resultData->indicator;
1448     resultData->return_code = 0;
1449     *rcodep = &resultData->return_code;
1450 #if 0
1451     printf("long_data_piece_size: %u\n", resultData->long_data_piece_size);
1452     printf("buffer_length: " FMT_U_MEM "\n", resultData->buffer_length);
1453     if (bufpp == NULL) {
1454       printf("OUT bufp: NULL\n");
1455     } else if (*bufpp == NULL) {
1456       printf("OUT bufp: *NULL*\n");
1457     } else {
1458       printf("OUT bufp: " FMT_U_MEM "\n", (memSizeType) *bufpp);
1459     } /* if */
1460     if (alenp == NULL) {
1461       printf("OUT alen: NULL\n");
1462     } else if (*alenp == NULL) {
1463       printf("OUT alen: *NULL*\n");
1464     } else {
1465       printf("OUT alen: " FMT_U_MEM "\n", (memSizeType) **alenp);
1466     } /* if */
1467     if (piecep == NULL) {
1468       printf("OUT piecep: NULL\n");
1469     } else if (*piecep == OCI_ONE_PIECE) {
1470       printf("OUT piecep: OCI_ONE_PIECE\n");
1471     } else if (*piecep == OCI_FIRST_PIECE) {
1472       printf("OUT piecep: OCI_FIRST_PIECE\n");
1473     } else if (*piecep == OCI_NEXT_PIECE) {
1474       printf("OUT piecep: OCI_NEXT_PIECE\n");
1475     } else {
1476       printf("OUT piecep: %u\n", *piecep);
1477     } /* if */
1478     if (indp == NULL) {
1479       printf("OUT ind: NULL\n");
1480     } else if (*indp == NULL) {
1481       printf("OUT ind: *NULL*\n");
1482     } else {
1483       printf("OUT ind: %lu\n", *(unsigned long *) *indp);
1484     } /* if */
1485 #endif
1486     return OCI_CONTINUE;
1487   } /* longCallback */
1488 
1489 
1490 
setupParameters(preparedStmtType preparedStmt,memSizeType numBindParameters)1491 static errInfoType setupParameters (preparedStmtType preparedStmt,
1492     memSizeType numBindParameters)
1493 
1494   {
1495     errInfoType err_info = OKAY_NO_ERROR;
1496 
1497   /* setupParameters */
1498     logFunction(printf("setupParameters\n"););
1499     if (numBindParameters == 0) {
1500       /* malloc(0) may return NULL, which would wrongly trigger a MEMORY_ERROR. */
1501       preparedStmt->param_array_size = 0;
1502       preparedStmt->param_array = NULL;
1503     } else if (unlikely(!ALLOC_TABLE(preparedStmt->param_array,
1504                                      bindDataRecord, numBindParameters))) {
1505       err_info = MEMORY_ERROR;
1506     } else {
1507       preparedStmt->param_array_size = numBindParameters;
1508       memset(preparedStmt->param_array, 0,
1509              numBindParameters * sizeof(bindDataRecord));
1510     } /* if */
1511     logFunction(printf("setupParameters --> %d\n", err_info););
1512     return err_info;
1513   } /* setupParameters */
1514 
1515 
1516 
setupResultColumn(preparedStmtType preparedStmt,unsigned int column_num,resultDataType resultData)1517 static errInfoType setupResultColumn (preparedStmtType preparedStmt,
1518     unsigned int column_num, resultDataType resultData)
1519 
1520   {
1521     ub4 column_size = 0;
1522     ub4 value_size;
1523     ub4 descriptor_type;
1524     enum {USE_BUFFER, USE_DESCRIPTOR, USE_REF} strategy = USE_BUFFER;
1525     errInfoType err_info = OKAY_NO_ERROR;
1526 
1527   /* setupResultColumn */
1528     if (OCIParamGet(preparedStmt->ppStmt, OCI_HTYPE_STMT,
1529                     preparedStmt->oci_error,
1530                     (dvoid **) &resultData->column_handle,
1531                     (ub4) column_num) != OCI_SUCCESS) {
1532       setDbErrorMsg("setupResultColumn", "OCIParamGet",
1533                     preparedStmt->oci_error);
1534       logError(printf("setupResultColumn: OCIParamGet:\n%s\n",
1535                       dbError.message););
1536       err_info = DATABASE_ERROR;
1537     } else if (OCIAttrGet(resultData->column_handle,
1538                           OCI_DTYPE_PARAM,
1539                           (dvoid *) &resultData->buffer_type,
1540                           NULL, OCI_ATTR_DATA_TYPE,
1541                           preparedStmt->oci_error) != OCI_SUCCESS) {
1542       setDbErrorMsg("setupResultColumn", "OCIAttrGet",
1543                     preparedStmt->oci_error);
1544       logError(printf("setupResultColumn: OCIAttrGet OCI_ATTR_DATA_TYPE:\n%s\n",
1545                       dbError.message););
1546       err_info = DATABASE_ERROR;
1547     } else if (OCIAttrGet(resultData->column_handle,
1548                           OCI_DTYPE_PARAM,
1549                           (dvoid *) &column_size, NULL, OCI_ATTR_DATA_SIZE,
1550                           preparedStmt->oci_error) != OCI_SUCCESS) {
1551       setDbErrorMsg("setupResultColumn", "OCIAttrGet",
1552                     preparedStmt->oci_error);
1553       logError(printf("setupResultColumn: OCIAttrGet OCI_ATTR_DATA_SIZE:\n%s\n",
1554                       dbError.message););
1555       err_info = DATABASE_ERROR;
1556     } else {
1557       value_size = column_size;
1558       switch (resultData->buffer_type) {
1559         case SQLT_LNG: /* LONG */
1560         case SQLT_LBI: /* LONG RAW */
1561           column_size = LONG_DATA_BUFFER_SIZE_INCREMENT;
1562           value_size = 2147483647; /* Maximum length of LONG data: 2**31-1 */
1563           strategy = USE_BUFFER;
1564           break;
1565         case SQLT_RDD: /* ROWID */
1566           descriptor_type = OCI_DTYPE_ROWID;  /* ROWID */
1567           column_size = 0;
1568           strategy = USE_DESCRIPTOR;
1569           break;
1570         case SQLT_BLOB: /* Binary LOB */
1571         case SQLT_CLOB: /* Character LOB  */
1572           descriptor_type = OCI_DTYPE_LOB;  /* Binary LOB or Character LOB */
1573           column_size = 0;
1574           strategy = USE_DESCRIPTOR;
1575           break;
1576         case SQLT_FILE: /* Binary FILE */
1577           descriptor_type = OCI_DTYPE_FILE;  /* Binary FILE */
1578           column_size = 0;
1579           strategy = USE_DESCRIPTOR;
1580           break;
1581         case SQLT_DATE:
1582           descriptor_type = OCI_DTYPE_DATE;  /* ANSI DATE */
1583           column_size = 0;
1584           strategy = USE_DESCRIPTOR;
1585           break;
1586         case SQLT_TIMESTAMP:
1587           descriptor_type = OCI_DTYPE_TIMESTAMP;  /* TIMESTAMP */
1588           column_size = 0;
1589           strategy = USE_DESCRIPTOR;
1590           break;
1591         case SQLT_TIMESTAMP_TZ:
1592           descriptor_type = OCI_DTYPE_TIMESTAMP_TZ;  /* TIMESTAMP WITH TIME ZONE */
1593           column_size = 0;
1594           strategy = USE_DESCRIPTOR;
1595           break;
1596         case SQLT_TIMESTAMP_LTZ:
1597           descriptor_type = OCI_DTYPE_TIMESTAMP_LTZ;  /* TIMESTAMP WITH LOCAL TIME ZONE */
1598           column_size = 0;
1599           strategy = USE_DESCRIPTOR;
1600           break;
1601         case SQLT_INTERVAL_YM:
1602           descriptor_type = OCI_DTYPE_INTERVAL_YM;  /* INTERVAL YEAR TO MONTH descriptor */
1603           column_size = 0;
1604           strategy = USE_DESCRIPTOR;
1605           break;
1606         case SQLT_INTERVAL_DS:
1607           descriptor_type = OCI_DTYPE_INTERVAL_DS;  /* INTERVAL DAY TO SECOND descriptor */
1608           column_size = 0;
1609           strategy = USE_DESCRIPTOR;
1610           break;
1611         case SQLT_REF: /* REF */
1612           resultData->buffer = NULL;
1613           resultData->ref = NULL;
1614           value_size = 0;
1615           strategy = USE_REF;
1616           break;
1617         case SQLT_CHR: /* VARCHAR2 */
1618         case SQLT_NUM: /* NUMBER */
1619         case SQLT_STR: /* NULL-terminated STRING */
1620         case SQLT_VCS: /* VARCHAR */
1621         case SQLT_DAT: /* DATE */
1622         case SQLT_VBI: /* VARRAW */
1623         case SQLT_BFLOAT:  /* BINARY_FLOAT */
1624         case SQLT_BDOUBLE: /* BINARY_DOUBLE */
1625         case SQLT_BIN: /* RAW */
1626         case SQLT_LVC: /* LONG VARCHAR */
1627         case SQLT_LVB: /* LONG VARRAW */
1628         case SQLT_AFC: /* CHAR */
1629         case SQLT_AVC: /* CHARZ */
1630         case SQLT_VST: /* OCI STRING type */
1631           strategy = USE_BUFFER;
1632           break;
1633         case SQLT_IBFLOAT:  /* BINARY_FLOAT */
1634           resultData->buffer_type = SQLT_BFLOAT;
1635           strategy = USE_BUFFER;
1636           break;
1637         case SQLT_IBDOUBLE: /* BINARY_DOUBLE */
1638           resultData->buffer_type = SQLT_BDOUBLE;
1639           strategy = USE_BUFFER;
1640           break;
1641         default:
1642           logError(printf("setupResultColumn: Column %u has the unknown type %s.\n",
1643                           column_num, nameOfBufferType(resultData->buffer_type)););
1644           err_info = RANGE_ERROR;
1645          break;
1646       } /* switch */
1647       if (err_info == OKAY_NO_ERROR) {
1648         if (strategy == USE_DESCRIPTOR) {
1649           if (OCIDescriptorAlloc(preparedStmt->oci_environment,
1650                                  &resultData->descriptor,
1651                                  descriptor_type,
1652                                  0, NULL) != OCI_SUCCESS) {
1653             logError(printf("setupResultColumn: OCIDescriptorAlloc: Out of memory.\n"););
1654             err_info = MEMORY_ERROR;
1655           } else {
1656             resultData->buffer = &resultData->descriptor;
1657           } /* if */
1658         } else if (strategy == USE_BUFFER) {
1659           /* printf ("column_size: " FMT_U32 "\n", column_size); */
1660           resultData->buffer = malloc(column_size);
1661           if (unlikely(resultData->buffer == NULL)) {
1662             err_info = MEMORY_ERROR;
1663           } else {
1664             memset(resultData->buffer, 0, column_size);
1665           } /* if */
1666         } /* if */
1667       } /* if */
1668       if (err_info == OKAY_NO_ERROR) {
1669         resultData->buffer_length = (memSizeType) column_size;
1670         /* printf("Define column %u: %s, len " FMT_U_MEM "\n", column_num,
1671                nameOfBufferType(resultData->buffer_type),
1672                resultData->buffer_length); */
1673         if (OCIDefineByPos(preparedStmt->ppStmt,
1674                            &resultData->define_handle,
1675                            preparedStmt->oci_error,
1676                            column_num,
1677                            resultData->buffer,
1678                            (sb4) value_size,
1679                            resultData->buffer_type,
1680                            &resultData->indicator,
1681                            &resultData->length,
1682                            NULL,
1683                            resultData->buffer_type == SQLT_LNG ||
1684                            resultData->buffer_type == SQLT_LBI ?
1685                            OCI_DYNAMIC_FETCH : OCI_DEFAULT) != OCI_SUCCESS) {
1686                            /* OCI_DEFAULT) != OCI_SUCCESS) { */
1687           setDbErrorMsg("setupResultColumn", "OCIDefineByPos",
1688                         preparedStmt->oci_error);
1689           logError(printf("setupResultColumn: OCIDefineByPos:\n%s\n",
1690                           dbError.message););
1691           err_info = DATABASE_ERROR;
1692         } else if (resultData->buffer_type == SQLT_LNG ||
1693                    resultData->buffer_type == SQLT_LBI) {
1694           /* printf("OCIDefineDynamic\n"); */
1695           if (OCIDefineDynamic(resultData->define_handle,
1696                                preparedStmt->oci_error,
1697                                resultData,
1698                                longCallback) != OCI_SUCCESS) {
1699             setDbErrorMsg("setupResultColumn", "OCIDefineDynamic",
1700                           preparedStmt->oci_error);
1701             logError(printf("setupResultColumn: OCIDefineDynamic:\n%s\n",
1702                             dbError.message););
1703             err_info = DATABASE_ERROR;
1704           } /* if */
1705         } else if (resultData->buffer_type == SQLT_REF) {
1706           /* printf("OCIDefineObject\n"); */
1707           if (OCIDefineObject(resultData->define_handle,
1708                               preparedStmt->oci_error,
1709                               NULL,
1710                               (dvoid **) &resultData->ref,
1711                               NULL, NULL, NULL) != OCI_SUCCESS) {
1712             setDbErrorMsg("setupResultColumn", "OCIDefineObject",
1713                           preparedStmt->oci_error);
1714             logError(printf("setupResultColumn: OCIDefineObject:\n%s\n",
1715                             dbError.message););
1716             err_info = DATABASE_ERROR;
1717           } /* if */
1718         } /* if */
1719       } /* if */
1720     } /* if */
1721     return err_info;
1722   } /* setupResultColumn */
1723 
1724 
1725 
setupResult(preparedStmtType preparedStmt)1726 static errInfoType setupResult (preparedStmtType preparedStmt)
1727 
1728   {
1729     ub4 num_columns = 0;
1730     unsigned int column_index;
1731     errInfoType err_info = OKAY_NO_ERROR;
1732 
1733   /* setupResult */
1734     logFunction(printf("setupResult\n"););
1735     if (OCIAttrGet(preparedStmt->ppStmt,
1736                    OCI_HTYPE_STMT,
1737                    &preparedStmt->statementType,
1738                    NULL,
1739                    OCI_ATTR_STMT_TYPE,
1740                    preparedStmt->oci_error) != OCI_SUCCESS) {
1741       setDbErrorMsg("setupResult", "OCIAttrGet",
1742                     preparedStmt->oci_error);
1743       logError(printf("setupResult: OCIAttrGet OCI_ATTR_STMT_TYPE:\n%s\n",
1744                       dbError.message););
1745       err_info = DATABASE_ERROR;
1746     } else if (preparedStmt->statementType == OCI_STMT_SELECT) {
1747       if (OCIStmtExecute(preparedStmt->oci_service_context,
1748                          preparedStmt->ppStmt,
1749                          preparedStmt->oci_error,
1750                          0, /* iters */
1751                          0, NULL, NULL, OCI_DESCRIBE_ONLY) != OCI_SUCCESS) {
1752         setDbErrorMsg("setupResult", "OCIStmtExecute",
1753                       preparedStmt->oci_error);
1754         logError(printf("setupResult: OCIStmtExecute OCI_DESCRIBE_ONLY:\n%s\n",
1755                       dbError.message););
1756         err_info = DATABASE_ERROR;
1757       } else if (OCIAttrGet(preparedStmt->ppStmt, OCI_HTYPE_STMT,
1758                             &num_columns, NULL, OCI_ATTR_PARAM_COUNT,
1759                             preparedStmt->oci_error) != OCI_SUCCESS) {
1760         setDbErrorMsg("setupResult", "OCIAttrGet",
1761                       preparedStmt->oci_error);
1762         logError(printf("setupResult: OCIAttrGet OCI_ATTR_PARAM_COUNT:\n%s\n",
1763                         dbError.message););
1764         err_info = DATABASE_ERROR;
1765       } else if (num_columns == 0) {
1766         /* malloc(0) may return NULL, which would wrongly trigger a MEMORY_ERROR. */
1767         preparedStmt->result_array_size = 0;
1768         preparedStmt->result_array = NULL;
1769       } else if (!ALLOC_TABLE(preparedStmt->result_array, resultDataRecord, num_columns)) {
1770         err_info = MEMORY_ERROR;
1771       } else {
1772         preparedStmt->result_array_size = num_columns;
1773         memset(preparedStmt->result_array, 0, num_columns * sizeof(resultDataRecord));
1774         for (column_index = 0; column_index < num_columns &&
1775              err_info == OKAY_NO_ERROR; column_index++) {
1776           err_info = setupResultColumn(preparedStmt, column_index + 1,
1777                                        &preparedStmt->result_array[column_index]);
1778         } /* for */
1779       } /* if */
1780     } /* if */
1781     logFunction(printf("setupResult --> %d\n", err_info););
1782     return err_info;
1783   } /* setupResult */
1784 
1785 
1786 
allParametersBound(preparedStmtType preparedStmt)1787 static boolType allParametersBound (preparedStmtType preparedStmt)
1788 
1789   {
1790     memSizeType column_index;
1791     boolType okay = TRUE;
1792 
1793   /* allParametersBound */
1794     for (column_index = 0; column_index < preparedStmt->param_array_size;
1795          column_index++) {
1796       if (unlikely(!preparedStmt->param_array[column_index].bound)) {
1797         logError(printf("sqlExecute: Unbound parameter " FMT_U_MEM ".\n",
1798                         column_index + 1););
1799         okay = FALSE;
1800       } /* if */
1801     } /* for */
1802     return okay;
1803   } /* allParametersBound */
1804 
1805 
1806 
1807 #ifdef SHOW_DETAILS
showBindVars(preparedStmtType preparedStmt)1808 static void showBindVars (preparedStmtType preparedStmt)
1809 
1810   {
1811     memSizeType pos;
1812     sb2 year;
1813     ub1 month;
1814     ub1 day;
1815     ub1 hour;
1816     ub1 min;
1817     ub1 sec;
1818     ub4 fsec;
1819 
1820   /* showBindVars */
1821     printf("Bind variables:\n");
1822     for (pos = 0; pos < preparedStmt->param_array_size; pos++) {
1823       printf(FMT_U_MEM ": type: %s, buf_len: " FMT_U_MEM ", ",
1824              pos + 1,
1825              nameOfBufferType(preparedStmt->param_array[pos].buffer_type),
1826              preparedStmt->param_array[pos].buffer_length);
1827       if (preparedStmt->param_array[pos].buffer == NULL) {
1828         printf("NULL");
1829       } else {
1830         if (preparedStmt->param_array[pos].buffer_type == SQLT_TIMESTAMP_TZ) {
1831           OCIDateTimeGetDate(preparedStmt->oci_environment,
1832                              preparedStmt->oci_error,
1833                              (OCIDateTime *) preparedStmt->param_array[pos].buffer,
1834                              &year,
1835                              &month,
1836                              &day);
1837           OCIDateTimeGetTime(preparedStmt->oci_environment,
1838                              preparedStmt->oci_error,
1839                              (OCIDateTime *) preparedStmt->param_array[pos].buffer,
1840                              &hour,
1841                              &min,
1842                              &sec,
1843                              &fsec);
1844           printf("%d-%02u-%02u %02u:%02u:%02u.%06u", year, month, day, hour, min, sec, fsec);
1845         } else {
1846           printBuffer(preparedStmt->param_array[pos].buffer_type,
1847                       preparedStmt->param_array[pos].buffer_length,
1848                       preparedStmt->param_array[pos].buffer);
1849         } /* if */
1850       } /* if */
1851       printf("\n");
1852     } /* for */
1853   } /* showBindVars */
1854 
1855 
1856 
showResultVars(preparedStmtType preparedStmt)1857 static void showResultVars (preparedStmtType preparedStmt)
1858 
1859   {
1860     memSizeType pos;
1861 
1862   /* showResultVars */
1863     printf("Result variables:\n");
1864     for (pos = 0; pos < preparedStmt->result_array_size; pos++) {
1865       printf(FMT_U_MEM ": type: %s, ind: %d, len: %u, buf_len: " FMT_U_MEM ", ",
1866              pos + 1,
1867              nameOfBufferType(preparedStmt->result_array[pos].buffer_type),
1868              preparedStmt->result_array[pos].indicator,
1869              preparedStmt->result_array[pos].length,
1870              preparedStmt->result_array[pos].buffer_length);
1871       printBuffer(preparedStmt->result_array[pos].buffer_type,
1872                   preparedStmt->result_array[pos].length,
1873                   preparedStmt->result_array[pos].buffer);
1874       printf("\n");
1875     } /* for */
1876   } /* showResultVars */
1877 #endif
1878 
1879 
1880 
getInt(const void * buffer,memSizeType length)1881 static intType getInt (const void *buffer, memSizeType length)
1882 
1883   {
1884     union {
1885       struct striStruct striBuf;
1886       char charBuf[SIZ_STRI(127)];
1887     } striBuffer;
1888     errInfoType err_info = OKAY_NO_ERROR;
1889     intType intValue;
1890 
1891   /* getInt */
1892     logFunction(printf("getInt(buffer, " FMT_U_MEM ")\n",
1893                        (memSizeType) length););
1894 #if ALLOW_STRITYPE_SLICES
1895     striBuffer.striBuf.mem = striBuffer.striBuf.mem1;
1896 #endif
1897     err_info = sqltNumberToDecimalInt(length,
1898                                       (uint8Type *) buffer,
1899                                       &striBuffer.striBuf);
1900     if (unlikely(err_info != OKAY_NO_ERROR)) {
1901       raise_error(err_info);
1902       intValue = 0;
1903     } else {
1904       /* printf("getInt: %s\n", striAsUnquotedCStri(&striBuffer.striBuf)); */
1905       intValue = intParse(&striBuffer.striBuf);
1906     } /* if */
1907     logFunction(printf("getInt --> " FMT_D "\n", intValue););
1908     return intValue;
1909   } /* getInt */
1910 
1911 
1912 
getBigInt(const void * buffer,memSizeType length)1913 static bigIntType getBigInt (const void *buffer, memSizeType length)
1914 
1915   {
1916     union {
1917       struct striStruct striBuf;
1918       char charBuf[SIZ_STRI(127)];
1919     } striBuffer;
1920     errInfoType err_info = OKAY_NO_ERROR;
1921     bigIntType bigIntValue;
1922 
1923   /* getBigInt */
1924 #if ALLOW_STRITYPE_SLICES
1925     striBuffer.striBuf.mem = striBuffer.striBuf.mem1;
1926 #endif
1927     err_info = sqltNumberToDecimalInt(length,
1928                                       (uint8Type *) buffer,
1929                                       &striBuffer.striBuf);
1930     if (unlikely(err_info != OKAY_NO_ERROR)) {
1931       raise_error(err_info);
1932       bigIntValue = NULL;
1933     } else {
1934       bigIntValue = bigParse(&striBuffer.striBuf);
1935     } /* if */
1936     return bigIntValue;
1937   } /* getBigInt */
1938 
1939 
1940 
getBigRational(const void * buffer,memSizeType length,bigIntType * denominator)1941 static bigIntType getBigRational (const void *buffer, memSizeType length,
1942     bigIntType *denominator)
1943 
1944   {
1945     union {
1946       struct striStruct striBuf;
1947       char charBuf[SIZ_STRI(127)];
1948     } striBuffer;
1949     int scale;
1950     errInfoType err_info = OKAY_NO_ERROR;
1951     bigIntType numerator;
1952 
1953   /* getBigRational */
1954     logFunction(printf("getBigRational(");
1955                 dumpSqltNumber(length, (const uint8Type *) buffer);
1956                 printf(")\n"););
1957 #if ALLOW_STRITYPE_SLICES
1958     striBuffer.striBuf.mem = striBuffer.striBuf.mem1;
1959 #endif
1960     scale = sqltNumberToDecimalFraction(length,
1961                                         (uint8Type *) buffer,
1962                                         &striBuffer.striBuf, &err_info);
1963     if (unlikely(err_info != OKAY_NO_ERROR)) {
1964       *denominator = NULL;
1965       raise_error(err_info);
1966       numerator = NULL;
1967     } else {
1968       numerator = bigParse(&striBuffer.striBuf);
1969       if (numerator != NULL) {
1970         if (scale == -1) {
1971           /* For positive and negative infinite values the scale is -1. */
1972           /* Not a Number (NaN), defined by this driver also uses -1. */
1973           *denominator = bigZero();
1974         } else {
1975           *denominator = bigIPowSignedDigit(10, (intType) scale);
1976         } /* if */
1977       } /* if */
1978     } /* if */
1979     logFunction(printf("getBigRational --> %s, %s\n",
1980                        bigHexCStri(numerator), bigHexCStri(*denominator)););
1981     return numerator;
1982   } /* getBigRational */
1983 
1984 
1985 
getFloat(const void * buffer,memSizeType length)1986 static floatType getFloat (const void *buffer, memSizeType length)
1987 
1988   {
1989     union {
1990       struct striStruct striBuf;
1991       char charBuf[SIZ_STRI(127)];
1992     } striBuffer;
1993     int scale;
1994     char cstriBuf[127 + 2 + NULL_TERMINATION_LEN];
1995     memSizeType precision;
1996     memSizeType pos = 0;
1997     memSizeType destPos = 0;
1998     errInfoType err_info = OKAY_NO_ERROR;
1999     floatType floatValue;
2000 
2001   /* getFloat */
2002     logFunction(printf("getFloat(");
2003                 dumpSqltNumber(length, (const uint8Type *) buffer);
2004                 printf(")\n"););
2005 #if ALLOW_STRITYPE_SLICES
2006     striBuffer.striBuf.mem = striBuffer.striBuf.mem1;
2007 #endif
2008     scale = sqltNumberToDecimalFraction(length,
2009                                         (uint8Type *) buffer,
2010                                         &striBuffer.striBuf, &err_info);
2011     if (unlikely(err_info != OKAY_NO_ERROR)) {
2012       raise_error(err_info);
2013       floatValue = 0.0;
2014     } else if (scale < 0) {
2015       /* For positive and negative infinite values the scale is -1. */
2016       /* Not a Number (NaN), defined by this driver also uses -1. */
2017       /* printf("scale = -1: %c\n", striBuffer.striBuf.mem[0]); */
2018       if (striBuffer.striBuf.mem[0] == '1') {
2019         floatValue = POSITIVE_INFINITY;
2020       } else if (striBuffer.striBuf.mem[0] == '0') {
2021         floatValue = NOT_A_NUMBER;
2022       } else {
2023         floatValue = NEGATIVE_INFINITY;
2024       } /* if */
2025     } else {
2026       /* printf("digits: %s\n", striAsUnquotedCStri(&striBuffer.striBuf));
2027          printf("scale: %d\n", scale); */
2028       if (striBuffer.striBuf.mem[0] == '-') {
2029         cstriBuf[destPos++] = '-';
2030         pos++;
2031       } /* if */
2032       precision = striBuffer.striBuf.size - pos;
2033       if ((memSizeType) scale < precision) {
2034         for (; pos < striBuffer.striBuf.size - (memSizeType) scale; pos++) {
2035           cstriBuf[destPos++] = (char) striBuffer.striBuf.mem[pos];
2036         } /* for */
2037         cstriBuf[destPos++] = '.';
2038       } else {
2039         cstriBuf[destPos++] = '0';
2040         cstriBuf[destPos++] = '.';
2041         memset(&cstriBuf[destPos], '0', (memSizeType) scale - precision);
2042         destPos += (memSizeType) scale - precision;
2043       } /* if */
2044       for (; pos < striBuffer.striBuf.size; pos++) {
2045         cstriBuf[destPos++] = (char) striBuffer.striBuf.mem[pos];
2046       } /* for */
2047       cstriBuf[destPos] = '\0';
2048       /* printf("cstri: %s\n", cstriBuf); */
2049       floatValue = (floatType) strtod(cstriBuf, NULL);
2050     } /* if */
2051     logFunction(printf("getFloat --> " FMT_E "\n", floatValue););
2052     return floatValue;
2053   } /* getFloat */
2054 
2055 
2056 
getRowid(preparedStmtType preparedStmt,OCIRowid * rowidDescriptor,errInfoType * err_info)2057 static striType getRowid (preparedStmtType preparedStmt,
2058     OCIRowid *rowidDescriptor, errInfoType *err_info)
2059 
2060   {
2061     ub2 length = 0;
2062     striType stri;
2063 
2064   /* getRowid */
2065     logFunction(printf("getRowid(" FMT_U_MEM ", " FMT_X_MEM ")\n",
2066                        (memSizeType) preparedStmt,
2067                        (memSizeType) rowidDescriptor););
2068     OCIRowidToChar(rowidDescriptor, NULL, &length, preparedStmt->oci_error);
2069     /* printf("length: %u\n", length); */
2070     if (unlikely(!ALLOC_STRI_SIZE_OK(stri, length))) {
2071       *err_info = MEMORY_ERROR;
2072     } else if (OCIRowidToChar(rowidDescriptor,
2073                               (OraText *) stri->mem, &length,
2074                               preparedStmt->oci_error) != OCI_SUCCESS) {
2075       setDbErrorMsg("getRowid", "OCIRowidToChar",
2076                     preparedStmt->oci_error);
2077       logError(printf("getRowid: OCIRowidToChar:\n%s\n",
2078                       dbError.message););
2079       *err_info = DATABASE_ERROR;
2080       FREE_STRI(stri, length);
2081       stri = NULL;
2082     } else {
2083       stri->size = length;
2084       memcpy_to_strelem(stri->mem, (ustriType) stri->mem, (memSizeType) length);
2085     } /* if */
2086     return stri;
2087   } /* getRowid */
2088 
2089 
2090 
getRef(preparedStmtType preparedStmt,OCIRef * ref,errInfoType * err_info)2091 static striType getRef (preparedStmtType preparedStmt, OCIRef *ref,
2092     errInfoType *err_info)
2093 
2094   {
2095     ub4 length;
2096     striType stri;
2097 
2098   /* getRef */
2099     length = OCIRefHexSize(preparedStmt->oci_environment, ref);
2100     if (unlikely(!ALLOC_STRI_CHECK_SIZE(stri, length))) {
2101       *err_info = MEMORY_ERROR;
2102     } else if (OCIRefToHex(preparedStmt->oci_environment,
2103                            preparedStmt->oci_error,
2104                            ref, (OraText *) stri->mem,
2105                            &length) != OCI_SUCCESS) {
2106       setDbErrorMsg("getRef", "OCIRefToHex",
2107                     preparedStmt->oci_error);
2108       logError(printf("getRef: OCIRefToHex:\n%s\n",
2109                       dbError.message););
2110       *err_info = DATABASE_ERROR;
2111       FREE_STRI(stri, length);
2112       stri = NULL;
2113     } else {
2114       stri->size = length;
2115       memcpy_to_strelem(stri->mem, (ustriType) stri->mem,
2116                         (memSizeType) length);
2117     } /* if */
2118     return stri;
2119   } /* getRef */
2120 
2121 
2122 
getBlob(preparedStmtType preparedStmt,OCILobLocator * lobLocator,errInfoType * err_info)2123 static bstriType getBlob (preparedStmtType preparedStmt,
2124     OCILobLocator *lobLocator, errInfoType *err_info)
2125 
2126   {
2127     oraub8 lobLength;
2128     oraub8 byte_amount;
2129     bstriType bstri;
2130 
2131   /* getBlob */
2132     logFunction(printf("getBlob(" FMT_U_MEM ", " FMT_X_MEM ")\n",
2133                        (memSizeType) preparedStmt,
2134                        (memSizeType) lobLocator););
2135     if (OCILobGetLength2(preparedStmt->oci_service_context,
2136                          preparedStmt->oci_error,
2137                          lobLocator,
2138                          &lobLength) != OCI_SUCCESS) {
2139       setDbErrorMsg("getBlob", "OCILobGetLength2",
2140                     preparedStmt->oci_error);
2141       logError(printf("getBlob: OCILobGetLength2:\n%s\n",
2142                       dbError.message););
2143       *err_info = DATABASE_ERROR;
2144       bstri = NULL;
2145     } else if (unlikely(lobLength > MAX_BSTRI_LEN ||
2146                         !ALLOC_BSTRI_SIZE_OK(bstri, (memSizeType) lobLength))) {
2147       *err_info = MEMORY_ERROR;
2148       bstri = NULL;
2149     } else {
2150       /* printf("lobLength: " FMT_U64 "\n", (uint64Type) lobLength); */
2151       byte_amount = lobLength;
2152       if (OCILobRead2(preparedStmt->oci_service_context,
2153                       preparedStmt->oci_error,
2154                       lobLocator,
2155                       &byte_amount,
2156                       NULL,
2157                       1,  /* Offsets should be greater than or equal to one. */
2158                       bstri->mem,
2159                       lobLength,
2160                       OCI_ONE_PIECE,
2161                       NULL, NULL, preparedStmt->charSetId, SQLCS_IMPLICIT) != OCI_SUCCESS) {
2162         setDbErrorMsg("getBlob", "OCILobRead2",
2163                       preparedStmt->oci_error);
2164         logError(printf("getBlob: OCILobRead2:\n%s\n",
2165                         dbError.message););
2166         *err_info = DATABASE_ERROR;
2167         FREE_BSTRI(bstri, (memSizeType) lobLength);
2168         bstri = NULL;
2169       } else {
2170         bstri->size = (memSizeType) lobLength;
2171       } /* if */
2172     } /* if */
2173     return bstri;
2174   } /* getBlob */
2175 
2176 
2177 
getBlobAsStri(preparedStmtType preparedStmt,OCILobLocator * lobLocator,errInfoType * err_info)2178 static striType getBlobAsStri (preparedStmtType preparedStmt,
2179     OCILobLocator *lobLocator, errInfoType *err_info)
2180 
2181   {
2182     oraub8 lobLength;
2183     oraub8 byte_amount;
2184     striType stri;
2185 
2186   /* getBlobAsStri */
2187     logFunction(printf("getBlobAsStri(" FMT_U_MEM ", " FMT_X_MEM ")\n",
2188                        (memSizeType) preparedStmt,
2189                        (memSizeType) lobLocator););
2190     if (OCILobGetLength2(preparedStmt->oci_service_context,
2191                          preparedStmt->oci_error,
2192                          lobLocator,
2193                          &lobLength) != OCI_SUCCESS) {
2194       setDbErrorMsg("getBlobAsStri", "OCILobGetLength2",
2195                     preparedStmt->oci_error);
2196       logError(printf("getBlobAsStri: OCILobGetLength2:\n%s\n",
2197                       dbError.message););
2198       *err_info = DATABASE_ERROR;
2199       stri = NULL;
2200     } else if (unlikely(lobLength > MAX_STRI_LEN ||
2201                         !ALLOC_STRI_SIZE_OK(stri, (memSizeType) lobLength))) {
2202       *err_info = MEMORY_ERROR;
2203       stri = NULL;
2204     } else {
2205       /* printf("lobLength: " FMT_U64 "\n", (uint64Type) lobLength); */
2206       byte_amount = lobLength;
2207       if (OCILobRead2(preparedStmt->oci_service_context,
2208                       preparedStmt->oci_error,
2209                       lobLocator,
2210                       &byte_amount,
2211                       NULL,
2212                       1,  /* Offsets should be greater than or equal to one. */
2213                       stri->mem,
2214                       lobLength,
2215                       OCI_ONE_PIECE,
2216                       NULL, NULL, preparedStmt->charSetId, SQLCS_IMPLICIT) != OCI_SUCCESS) {
2217         setDbErrorMsg("getBlobAsStri", "OCILobRead2",
2218                       preparedStmt->oci_error);
2219         logError(printf("getBlobAsStri: OCILobRead2:\n%s\n",
2220                         dbError.message););
2221         *err_info = DATABASE_ERROR;
2222         FREE_STRI(stri, (memSizeType) lobLength);
2223         stri = NULL;
2224       } else {
2225         memcpy_to_strelem(stri->mem, (ustriType) stri->mem, (memSizeType) lobLength);
2226         stri->size = (memSizeType) lobLength;
2227       } /* if */
2228     } /* if */
2229     return stri;
2230   } /* getBlobAsStri */
2231 
2232 
2233 
getClob(preparedStmtType preparedStmt,OCILobLocator * lobLocator,errInfoType * err_info)2234 static striType getClob (preparedStmtType preparedStmt,
2235     OCILobLocator *lobLocator, errInfoType *err_info)
2236 
2237   {
2238     oraub8 lobLength;
2239     oraub8 byte_amount;
2240     char *buffer;
2241     char *resized_buffer;
2242     memSizeType buffer_size;
2243     striType stri;
2244 
2245   /* getClob */
2246     logFunction(printf("getClob(" FMT_U_MEM ", " FMT_X_MEM ")\n",
2247                        (memSizeType) preparedStmt,
2248                        (memSizeType) lobLocator););
2249     if (OCILobGetLength2(preparedStmt->oci_service_context,
2250                          preparedStmt->oci_error,
2251                          lobLocator,
2252                          &lobLength) != OCI_SUCCESS) {
2253       setDbErrorMsg("getClob", "OCILobGetLength2",
2254                     preparedStmt->oci_error);
2255       logError(printf("getClob: OCILobGetLength2:\n%s\n",
2256                       dbError.message););
2257       *err_info = DATABASE_ERROR;
2258       stri = NULL;
2259     } else if (unlikely(lobLength > MAX_MEMSIZETYPE / MAX_UTF8_EXPANSION_FACTOR)) {
2260       *err_info = MEMORY_ERROR;
2261       stri = NULL;
2262     } else {
2263       /* printf("connection charset_id: %u\n", preparedStmt->charSetId);
2264          printf("SQLCS_IMPLICIT: %u\n", SQLCS_IMPLICIT);
2265          printf("lobLength: " FMT_U64 "\n", (uint64Type) lobLength); */
2266       buffer_size = (memSizeType) lobLength * MAX_UTF8_EXPANSION_FACTOR;
2267       if (unlikely((buffer = (char *) malloc(buffer_size)) == NULL)) {
2268         *err_info = MEMORY_ERROR;
2269         stri = NULL;
2270       } else {
2271         byte_amount = buffer_size;
2272         if (OCILobRead2(preparedStmt->oci_service_context,
2273                         preparedStmt->oci_error,
2274                         lobLocator,
2275                         &byte_amount,
2276                         NULL, /* Make sure that byte_amount is used. */
2277                         1,  /* Offsets should be greater than or equal to one. */
2278                         buffer,
2279                         buffer_size,
2280                         OCI_ONE_PIECE,
2281                         NULL, NULL, preparedStmt->charSetId, SQLCS_IMPLICIT) != OCI_SUCCESS) {
2282           setDbErrorMsg("getClob", "OCILobRead2",
2283                         preparedStmt->oci_error);
2284           logError(printf("getClob: OCILobRead2:\n%s\n",
2285                           dbError.message););
2286           *err_info = DATABASE_ERROR;
2287           stri = NULL;
2288         } else if (byte_amount > buffer_size) {
2289           *err_info = MEMORY_ERROR;
2290           stri = NULL;
2291         } else {
2292           /* printf("buffer_size: " FMT_U_MEM "\n", buffer_size);
2293              printf("byte_amount: " FMT_U64 "\n", (uint64Type) byte_amount); */
2294           if (lobLength > 1048576) {
2295             /* Reduce memory pressure. */
2296             resized_buffer = (char *) realloc(buffer, (memSizeType) byte_amount);
2297             if (resized_buffer != NULL) {
2298               buffer = resized_buffer;
2299             } /* if */
2300           } /* if */
2301           stri = cstri8_buf_to_stri(buffer, (memSizeType) byte_amount, err_info);
2302           /* printf("stri->size: " FMT_U_MEM "\n", stri->size); */
2303         } /* if */
2304         free(buffer);
2305       } /* if */
2306     } /* if */
2307     return stri;
2308   } /* getClob */
2309 
2310 
2311 
setBigInt(void * const buffer,const const_bigIntType bigIntValue,errInfoType * err_info)2312 static int setBigInt (void *const buffer, const const_bigIntType bigIntValue,
2313     errInfoType *err_info)
2314 
2315   {
2316     striType stri;
2317     int length = 0;
2318 
2319   /* setBigInt */
2320     logFunction(printf("setBigInt(*, %s, *)\n", bigHexCStri(bigIntValue)););
2321     stri = bigStr(bigIntValue);
2322     if (stri == NULL) {
2323       *err_info = MEMORY_ERROR;
2324     } else {
2325       length = sqltNumberFromDecimalInt((uint8Type *) buffer, stri, 0, err_info);
2326       FREE_STRI(stri, stri->size);
2327     } /* if */
2328     return length;
2329   } /* setBigInt */
2330 
2331 
2332 
setBigRat(void * const buffer,const const_bigIntType numerator,const const_bigIntType denominator,errInfoType * err_info)2333 static int setBigRat (void *const buffer, const const_bigIntType numerator,
2334     const const_bigIntType denominator, errInfoType *err_info)
2335 
2336   {
2337     bigIntType number;
2338     bigIntType mantissaValue = NULL;
2339     striType stri;
2340     int length = 0;
2341 
2342   /* setBigRat */
2343     logFunction(printf("setBigRat(*, %s, %s, *)\n",
2344                        bigHexCStri(numerator), bigHexCStri(denominator)););
2345     if (bigEqSignedDigit(denominator, 0)) {
2346       if (bigCmpSignedDigit(numerator, 0) > 0) {
2347         /* printf("Positive infinity\n"); */
2348         SET_NUMBER_TO_POSITIVE_INFINITY(buffer, length);
2349       } else if (bigEqSignedDigit(numerator, 0)) {
2350         /* Not a Number (NaN), defined by this driver. */
2351         /* printf("NaN\n"); */
2352         SET_NUMBER_TO_NAN(buffer, length);
2353       } else {
2354         /* printf("Negative infinity\n"); */
2355         SET_NUMBER_TO_NEGATIVE_INFINITY(buffer, length);
2356       } /* if */
2357     } else {
2358       number = bigIPowSignedDigit(10, 128);
2359       if (number != NULL) {
2360         bigMultAssign(&number, numerator);
2361         mantissaValue = bigDiv(number, denominator);
2362         bigDestr(number);
2363       } /* if */
2364       if (mantissaValue != NULL) {
2365         stri = bigStr(mantissaValue);
2366         if (stri == NULL) {
2367           *err_info = MEMORY_ERROR;
2368         } else {
2369           length = sqltNumberFromDecimalInt((uint8Type *) buffer, stri, 128, err_info);
2370           FREE_STRI(stri, stri->size);
2371         } /* if */
2372         bigDestr(mantissaValue);
2373       } /* if */
2374     } /* if */
2375     logFunction(printf("setBigRat --> ");
2376                 dumpSqltNumber((memSizeType) length, (const uint8Type *) buffer);
2377                 printf("\n"););
2378     return length;
2379   } /* setBigRat */
2380 
2381 
2382 
setBlob(preparedStmtType preparedStmt,OCILobLocator * lobLocator,const const_bstriType bstri,errInfoType * err_info)2383 static boolType setBlob (preparedStmtType preparedStmt,
2384     OCILobLocator *lobLocator, const const_bstriType bstri,
2385     errInfoType *err_info)
2386 
2387   {
2388     oraub8 byte_amount;
2389 
2390   /* setBlob */
2391     logFunction(printf("setBlob(" FMT_U_MEM ", " FMT_X_MEM ", *, *)\n",
2392                        (memSizeType) preparedStmt,
2393                        (memSizeType) lobLocator););
2394     if (OCILobTrim2(preparedStmt->oci_service_context,
2395                     preparedStmt->oci_error,
2396                     lobLocator,
2397                     0) != OCI_SUCCESS) {
2398       setDbErrorMsg("setBlob", "OCILobTrim2",
2399                     preparedStmt->oci_error);
2400       logError(printf("setBlob: OCILobTrim2:\n%s\n",
2401                       dbError.message););
2402       *err_info = DATABASE_ERROR;
2403     } /* if */
2404     byte_amount = bstri->size;
2405     if (OCILobWrite2(preparedStmt->oci_service_context,
2406                      preparedStmt->oci_error,
2407                      lobLocator,
2408                      &byte_amount,
2409                      NULL,
2410                      1,  /* Offsets should be greater than or equal to one. */
2411                      (dvoid *) bstri->mem,
2412                      (oraub8) bstri->size,
2413                      OCI_ONE_PIECE, NULL, NULL,
2414                      preparedStmt->charSetId, SQLCS_IMPLICIT) != OCI_SUCCESS) {
2415       setDbErrorMsg("setBlob", "OCILobWrite2",
2416                     preparedStmt->oci_error);
2417       logError(printf("setBlob: OCILobWrite2:\n%s\n",
2418                       dbError.message););
2419       *err_info = DATABASE_ERROR;
2420     } /* if */
2421     return *err_info == OKAY_NO_ERROR;
2422   } /* setBlob */
2423 
2424 
2425 
2426 #ifndef SQLT_BFLOAT
setFloat(void * const buffer,const floatType floatValue,errInfoType * err_info)2427 static int setFloat (void *const buffer, const floatType floatValue,
2428     errInfoType *err_info)
2429 
2430   {
2431     striType stri;
2432     memSizeType decimalPointPos;
2433     memSizeType scale;
2434     memSizeType savedSize;
2435     int length = 0;
2436 
2437   /* setFloat */
2438     logFunction(printf("setFloat(" FMT_E ")\n", floatValue););
2439     if (os_isnan(floatValue)) {
2440       /* Not a Number (NaN), defined by this driver. */
2441       /* printf("NaN\n"); */
2442       SET_NUMBER_TO_NAN(buffer, length);
2443     } else if (os_isinf(floatValue)) {
2444       if (floatValue < 0.0) {
2445         /* printf("Negative infinity\n"); */
2446         SET_NUMBER_TO_NEGATIVE_INFINITY(buffer, length);
2447       } else {
2448         /* printf("Positive infinity\n"); */
2449         SET_NUMBER_TO_POSITIVE_INFINITY(buffer, length);
2450       } /* if */
2451     } else {
2452 #if FLOATTYPE_SIZE == 32
2453       stri = doubleToStri(floatValue, FALSE);
2454 #elif FLOATTYPE_SIZE == 64
2455       stri = doubleToStri(floatValue, TRUE);
2456 #else
2457       stri = NULL;
2458 #endif
2459       if (stri == NULL) {
2460         *err_info = MEMORY_ERROR;
2461       } else {
2462         /* printf("stri: ");
2463            prot_stri(stri);
2464            printf("\n"); */
2465         decimalPointPos = (memSizeType) strChPos(stri, '.');
2466         scale = stri->size - decimalPointPos;
2467         memmove(&stri->mem[decimalPointPos - 1],
2468                 &stri->mem[decimalPointPos],
2469                 scale * sizeof(strElemType));
2470         savedSize = stri->size;
2471         stri->size--;
2472         while (scale >= 1 && stri->mem[stri->size - 1] == '0') {
2473           scale--;
2474           stri->size--;
2475         } /* while */
2476         if (scale > INT_MAX) {
2477           /* It is not possible to cast scale to int. */
2478           *err_info = MEMORY_ERROR;
2479         } else {
2480           length = sqltNumberFromDecimalInt((uint8Type *) buffer, stri, (int) scale, err_info);
2481         } /* if */
2482         FREE_STRI(stri, savedSize);
2483       } /* if */
2484     } /* if */
2485     logFunction(printf("setFloat --> ");
2486                 dumpSqltNumber((memSizeType) length, (const uint8Type *) buffer);
2487                 printf("\n"););
2488     return length;
2489   } /* setFloat */
2490 #endif
2491 
2492 
2493 
sqlBindBigInt(sqlStmtType sqlStatement,intType pos,const const_bigIntType value)2494 static void sqlBindBigInt (sqlStmtType sqlStatement, intType pos,
2495     const const_bigIntType value)
2496 
2497   {
2498     preparedStmtType preparedStmt;
2499     bindDataType param;
2500     int length;
2501     errInfoType err_info = OKAY_NO_ERROR;
2502 
2503   /* sqlBindBigInt */
2504     logFunction(printf("sqlBindBigInt(" FMT_U_MEM ", " FMT_D ", %s)\n",
2505                        (memSizeType) sqlStatement, pos, bigHexCStri(value)););
2506     preparedStmt = (preparedStmtType) sqlStatement;
2507     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
2508       logError(printf("sqlBindBigInt: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
2509                       pos, preparedStmt->param_array_size););
2510       raise_error(RANGE_ERROR);
2511     } else {
2512       param = &preparedStmt->param_array[pos - 1];
2513       if (param->buffer_capacity < SIZEOF_SQLT_NUM) {
2514         free(param->buffer);
2515         if ((param->buffer = malloc(SIZEOF_SQLT_NUM)) == NULL) {
2516           param->buffer_capacity = 0;
2517           err_info = MEMORY_ERROR;
2518         } else {
2519           param->buffer_capacity = SIZEOF_SQLT_NUM;
2520         } /* if */
2521       } /* if */
2522       if (unlikely(err_info != OKAY_NO_ERROR)) {
2523         raise_error(err_info);
2524       } else {
2525         param->buffer_type = SQLT_NUM;
2526         param->buffer_length = SIZEOF_SQLT_NUM;
2527         length = setBigInt(param->buffer, value, &err_info);
2528         if (unlikely(err_info != OKAY_NO_ERROR)) {
2529           raise_error(err_info);
2530         } else {
2531           if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
2532                                     &param->bind_handle,
2533                                     preparedStmt->oci_error,
2534                                     (ub4) pos,
2535                                     param->buffer,
2536                                     length,
2537                                     SQLT_NUM, NULL, NULL, NULL, 0, NULL,
2538                                     OCI_DEFAULT) != OCI_SUCCESS)) {
2539             setDbErrorMsg("sqlBindBigInt", "OCIBindByPos",
2540                           preparedStmt->oci_error);
2541             logError(printf("sqlBindBigInt: OCIBindByPos:\n%s\n",
2542                             dbError.message););
2543             raise_error(DATABASE_ERROR);
2544           } else {
2545             preparedStmt->executeSuccessful = FALSE;
2546             preparedStmt->fetchOkay = FALSE;
2547             param->bound = TRUE;
2548           } /* if */
2549         } /* if */
2550       } /* if */
2551     } /* if */
2552   } /* sqlBindBigInt */
2553 
2554 
2555 
sqlBindBigRat(sqlStmtType sqlStatement,intType pos,const const_bigIntType numerator,const const_bigIntType denominator)2556 static void sqlBindBigRat (sqlStmtType sqlStatement, intType pos,
2557     const const_bigIntType numerator, const const_bigIntType denominator)
2558 
2559   {
2560     preparedStmtType preparedStmt;
2561     bindDataType param;
2562     int length;
2563     errInfoType err_info = OKAY_NO_ERROR;
2564 
2565   /* sqlBindBigRat */
2566     logFunction(printf("sqlBindBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s)\n",
2567                        (memSizeType) sqlStatement, pos,
2568                        bigHexCStri(numerator), bigHexCStri(denominator)););
2569     preparedStmt = (preparedStmtType) sqlStatement;
2570     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
2571       logError(printf("sqlBindBigRat: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
2572                       pos, preparedStmt->param_array_size););
2573       raise_error(RANGE_ERROR);
2574     } else {
2575       param = &preparedStmt->param_array[pos - 1];
2576       if (param->buffer_capacity < SIZEOF_SQLT_NUM) {
2577         free(param->buffer);
2578         if ((param->buffer = malloc(SIZEOF_SQLT_NUM)) == NULL) {
2579           param->buffer_capacity = 0;
2580           err_info = MEMORY_ERROR;
2581         } else {
2582           param->buffer_capacity = SIZEOF_SQLT_NUM;
2583         } /* if */
2584       } /* if */
2585       if (unlikely(err_info != OKAY_NO_ERROR)) {
2586         raise_error(err_info);
2587       } else {
2588         param->buffer_type = SQLT_NUM;
2589         param->buffer_length = SIZEOF_SQLT_NUM;
2590         length = setBigRat(param->buffer, numerator, denominator, &err_info);
2591         if (unlikely(err_info != OKAY_NO_ERROR)) {
2592           raise_error(err_info);
2593         } else {
2594           if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
2595                                     &param->bind_handle,
2596                                     preparedStmt->oci_error,
2597                                     (ub4) pos,
2598                                     param->buffer,
2599                                     length,
2600                                     SQLT_NUM, NULL, NULL, NULL, 0, NULL,
2601                                     OCI_DEFAULT) != OCI_SUCCESS)) {
2602             setDbErrorMsg("sqlBindBigRat", "OCIBindByPos",
2603                           preparedStmt->oci_error);
2604             logError(printf("sqlBindBigRat: OCIBindByPos:\n%s\n",
2605                             dbError.message););
2606             raise_error(DATABASE_ERROR);
2607           } else {
2608             preparedStmt->executeSuccessful = FALSE;
2609             preparedStmt->fetchOkay = FALSE;
2610             param->bound = TRUE;
2611           } /* if */
2612         } /* if */
2613       } /* if */
2614     } /* if */
2615   } /* sqlBindBigRat */
2616 
2617 
2618 
sqlBindBool(sqlStmtType sqlStatement,intType pos,boolType value)2619 static void sqlBindBool (sqlStmtType sqlStatement, intType pos, boolType value)
2620 
2621   {
2622     preparedStmtType preparedStmt;
2623     bindDataType param;
2624     errInfoType err_info = OKAY_NO_ERROR;
2625 
2626   /* sqlBindBool */
2627     logFunction(printf("sqlBindBool(" FMT_U_MEM ", " FMT_D ", %s)\n",
2628                        (memSizeType) sqlStatement, pos, value ? "TRUE" : "FALSE"););
2629     preparedStmt = (preparedStmtType) sqlStatement;
2630     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
2631       logError(printf("sqlBindBool: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
2632                       pos, preparedStmt->param_array_size););
2633       raise_error(RANGE_ERROR);
2634     } else {
2635       param = &preparedStmt->param_array[pos - 1];
2636       if (param->buffer_capacity < 1) {
2637         if ((param->buffer = malloc(1)) == NULL) {
2638           param->buffer_capacity = 0;
2639           err_info = MEMORY_ERROR;
2640         } else {
2641           param->buffer_capacity = 1;
2642         } /* if */
2643       } /* if */
2644       if (unlikely(err_info != OKAY_NO_ERROR)) {
2645         raise_error(err_info);
2646       } else {
2647         param->buffer_type = SQLT_AFC;
2648         param->buffer_length = 1;
2649         ((char *) param->buffer)[0] = (char) ('0' + value);
2650         if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
2651                                   &param->bind_handle,
2652                                   preparedStmt->oci_error,
2653                                   (ub4) pos,
2654                                   param->buffer,
2655                                   (sb4) param->buffer_length,
2656                                   SQLT_AFC, NULL, NULL, NULL, 0, NULL,
2657                                   OCI_DEFAULT) != OCI_SUCCESS)) {
2658           setDbErrorMsg("sqlBindBool", "OCIBindByPos",
2659                         preparedStmt->oci_error);
2660           logError(printf("sqlBindBool: OCIBindByPos:\n%s\n",
2661                           dbError.message););
2662           raise_error(DATABASE_ERROR);
2663         } else {
2664           preparedStmt->executeSuccessful = FALSE;
2665           preparedStmt->fetchOkay = FALSE;
2666           param->bound = TRUE;
2667         } /* if */
2668       } /* if */
2669     } /* if */
2670   } /* sqlBindBool */
2671 
2672 
2673 
sqlBindBStri(sqlStmtType sqlStatement,intType pos,const const_bstriType bstri)2674 static void sqlBindBStri (sqlStmtType sqlStatement, intType pos,
2675     const const_bstriType bstri)
2676 
2677   {
2678     preparedStmtType preparedStmt;
2679     bindDataType param;
2680     errInfoType err_info = OKAY_NO_ERROR;
2681 
2682   /* sqlBindBStri */
2683     logFunction(printf("sqlBindBStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
2684                        (memSizeType) sqlStatement, pos, bstriAsUnquotedCStri(bstri)););
2685     preparedStmt = (preparedStmtType) sqlStatement;
2686     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
2687       logError(printf("sqlBindBStri: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
2688                       pos, preparedStmt->param_array_size););
2689       raise_error(RANGE_ERROR);
2690     } else {
2691       param = &preparedStmt->param_array[pos - 1];
2692       if (param->buffer_capacity < sizeof(void *)) {
2693         free(param->buffer);
2694         if ((param->buffer = malloc(sizeof(void *))) == NULL) {
2695           param->buffer_capacity = 0;
2696           err_info = MEMORY_ERROR;
2697         } else {
2698           param->buffer_capacity = sizeof(void *);
2699         } /* if */
2700       } /* if */
2701       if (likely(err_info == OKAY_NO_ERROR)) {
2702         if (param->buffer_type != SQLT_BLOB && param->descriptor != NULL) {
2703           freeDescriptor(preparedStmt,
2704                          param->descriptor,
2705                          param->buffer_type);
2706           param->descriptor = NULL;
2707         } /* if */
2708         if (param->descriptor == NULL) {
2709           if (OCIDescriptorAlloc(preparedStmt->oci_environment,
2710                                  &param->descriptor,
2711                                  OCI_DTYPE_LOB,  /* Binary LOB or Character LOB */
2712                                  0, NULL) != OCI_SUCCESS) {
2713             logError(printf("sqlBindBStri: OCIDescriptorAlloc: Out of memory.\n"););
2714             err_info = MEMORY_ERROR;
2715           } /* if */
2716         } /* if */
2717       } /* if */
2718       if (likely(err_info == OKAY_NO_ERROR)) {
2719         if (OCILobCreateTemporary(preparedStmt->oci_service_context,
2720                                   preparedStmt->oci_error,
2721                                   (OCILobLocator *) param->descriptor,
2722                                   OCI_DEFAULT,
2723                                   OCI_DEFAULT,
2724                                   OCI_TEMP_BLOB,
2725                                   FALSE,
2726                                   OCI_DURATION_SESSION) != OCI_SUCCESS) {
2727           setDbErrorMsg("sqlBindBStri", "OCILobCreateTemporary",
2728                         preparedStmt->oci_error);
2729           logError(printf("sqlBindBStri: OCILobCreateTemporary:\n%s\n",
2730                           dbError.message););
2731           err_info = DATABASE_ERROR;
2732         } else {
2733           *(void **) param->buffer = param->descriptor;
2734           param->buffer_type   = SQLT_BLOB;
2735           param->buffer_length = 0;
2736         } /* if */
2737       } /* if */
2738       if (unlikely(err_info != OKAY_NO_ERROR)) {
2739         raise_error(err_info);
2740       } else if (bstri->size == 0) {
2741         param->indicator = -1;
2742         if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
2743                                   &param->bind_handle,
2744                                   preparedStmt->oci_error,
2745                                   (ub4) pos,
2746                                   param->buffer,
2747                                   (sb4) param->buffer_length,
2748                                   SQLT_BLOB,
2749                                   &param->indicator,
2750                                   NULL, NULL, 0, NULL, OCI_DEFAULT) != OCI_SUCCESS))  {
2751           setDbErrorMsg("sqlBindBStri", "OCIBindByPos",
2752                         preparedStmt->oci_error);
2753           logError(printf("sqlBindBStri: OCIBindByPos:\n%s\n",
2754                           dbError.message););
2755           raise_error(DATABASE_ERROR);
2756         } else {
2757           preparedStmt->executeSuccessful = FALSE;
2758           preparedStmt->fetchOkay = FALSE;
2759           param->bound = TRUE;
2760         } /* if */
2761       } else if (unlikely(!setBlob(preparedStmt,
2762                                    (OCILobLocator *) param->descriptor,
2763                                    bstri, &err_info))) {
2764         raise_error(err_info);
2765       } else if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
2766                                        &param->bind_handle,
2767                                        preparedStmt->oci_error,
2768                                        (ub4) pos,
2769                                        param->buffer,
2770                                        (sb4) param->buffer_length,
2771                                        SQLT_BLOB,
2772                                        NULL, NULL, NULL, 0, NULL,
2773                                        OCI_DEFAULT) != OCI_SUCCESS))  {
2774         setDbErrorMsg("sqlBindBStri", "OCIBindByPos",
2775                       preparedStmt->oci_error);
2776         logError(printf("sqlBindBStri: OCIBindByPos:\n%s\n",
2777                         dbError.message););
2778         raise_error(DATABASE_ERROR);
2779       } else {
2780         preparedStmt->executeSuccessful = FALSE;
2781         preparedStmt->fetchOkay = FALSE;
2782         param->bound = TRUE;
2783       } /* if */
2784     } /* if */
2785   } /* sqlBindBStri */
2786 
2787 
2788 
sqlBindDuration(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second)2789 static void sqlBindDuration (sqlStmtType sqlStatement, intType pos,
2790     intType year, intType month, intType day, intType hour,
2791     intType minute, intType second, intType micro_second)
2792 
2793   {
2794     preparedStmtType preparedStmt;
2795     bindDataType param;
2796     uint16Type buffer_type;
2797     errInfoType err_info = OKAY_NO_ERROR;
2798 
2799   /* sqlBindDuration */
2800     logFunction(printf("sqlBindDuration(" FMT_U_MEM ", " FMT_D ", P"
2801                                           FMT_D "Y" FMT_D "M" FMT_D "DT"
2802                                           FMT_D "H" FMT_D "M%s" FMT_U "." F_U(06) "S)\n",
2803                        (memSizeType) sqlStatement, pos,
2804                        year, month, day, hour, minute,
2805                        second < 0 || micro_second < 0 ? "-" : "",
2806                        intAbs(second), intAbs(micro_second)););
2807     preparedStmt = (preparedStmtType) sqlStatement;
2808     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
2809       logError(printf("sqlBindDuration: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
2810                       pos, preparedStmt->param_array_size););
2811       raise_error(RANGE_ERROR);
2812     } else if (unlikely(year < INT32TYPE_MIN || year > INT32TYPE_MAX || month < -12 || month > 12 ||
2813                         day < -31 || day > 31 || hour <= -24 || hour >= 24 ||
2814                         minute <= -60 || minute >= 60 || second <= -60 || second >= 60 ||
2815                         micro_second <= -1000000 || micro_second >= 1000000)) {
2816       logError(printf("sqlBindDuration: Duration not in allowed range.\n"););
2817       raise_error(RANGE_ERROR);
2818     } else if (unlikely(!((year >= 0 && month >= 0 && day >= 0 && hour >= 0 &&
2819                            minute >= 0 && second >= 0 && micro_second >= 0) ||
2820                           (year <= 0 && month <= 0 && day <= 0 && hour <= 0 &&
2821                            minute <= 0 && second <= 0 && micro_second <= 0)))) {
2822       logError(printf("sqlBindDuration: Duration neither clearly positive nor negative.\n"););
2823       raise_error(RANGE_ERROR);
2824     } else {
2825       param = &preparedStmt->param_array[pos - 1];
2826       if (param->buffer_capacity < sizeof(void *)) {
2827         free(param->buffer);
2828         if ((param->buffer = malloc(sizeof(void *))) == NULL) {
2829           param->buffer_capacity = 0;
2830           err_info = MEMORY_ERROR;
2831         } else {
2832           param->buffer_capacity = sizeof(void *);
2833         } /* if */
2834       } /* if */
2835       if (likely(err_info == OKAY_NO_ERROR)) {
2836         if (day == 0 && hour == 0 && minute == 0 && second == 0 && micro_second == 0) {
2837           buffer_type = SQLT_INTERVAL_YM;
2838         } else if (year == 0 && month == 0) {
2839           buffer_type = SQLT_INTERVAL_DS;
2840         } else {
2841           logError(printf("sqlBindDuration: Neither SQLT_INTERVAL_YM nor SQLT_INTERVAL_DS.\n"););
2842           err_info = RANGE_ERROR;
2843         } /* if */
2844       } /* if */
2845       if (likely(err_info == OKAY_NO_ERROR)) {
2846         if (param->buffer_type != buffer_type && param->descriptor != NULL) {
2847           freeDescriptor(preparedStmt,
2848                          param->descriptor,
2849                          param->buffer_type);
2850           param->descriptor = NULL;
2851         } /* if */
2852         if (param->descriptor == NULL) {
2853           if (buffer_type == SQLT_INTERVAL_YM) {
2854             if (OCIDescriptorAlloc(preparedStmt->oci_environment,
2855                                    &param->descriptor,
2856                                    OCI_DTYPE_INTERVAL_YM,  /* INTERVAL YEAR TO MONTH descriptor */
2857                                    0, NULL) != OCI_SUCCESS) {
2858               logError(printf("sqlBindDuration: OCIDescriptorAlloc: Out of memory.\n"););
2859               err_info = MEMORY_ERROR;
2860             } /* if */
2861           } else if (buffer_type == SQLT_INTERVAL_DS) {
2862             if (OCIDescriptorAlloc(preparedStmt->oci_environment,
2863                                    &param->descriptor,
2864                                    OCI_DTYPE_INTERVAL_DS,  /* INTERVAL DAY TO SECOND descriptor */
2865                                    0, NULL) != OCI_SUCCESS) {
2866               logError(printf("sqlBindDuration: OCIDescriptorAlloc: Out of memory.\n"););
2867               err_info = MEMORY_ERROR;
2868             } /* if */
2869           } /* if */
2870         } /* if */
2871       } /* if */
2872       if (likely(err_info == OKAY_NO_ERROR)) {
2873         param->buffer_type = buffer_type;
2874         param->buffer_length = 0;
2875         *(void **) param->buffer = param->descriptor;
2876         if (buffer_type == SQLT_INTERVAL_YM) {
2877           if (OCIIntervalSetYearMonth(preparedStmt->oci_environment,
2878                                       preparedStmt->oci_error,
2879                                       (sb4) year,
2880                                       (sb4) month,
2881                                       (OCIInterval *) param->descriptor) != OCI_SUCCESS) {
2882             logError(printf("sqlBindDuration: OCIIntervalSetYearMonth:\n");
2883                      printError(preparedStmt->oci_error););
2884             err_info = RANGE_ERROR;
2885           } /* if */
2886         } else if (buffer_type == SQLT_INTERVAL_DS) {
2887           if (OCIIntervalSetDaySecond(preparedStmt->oci_environment,
2888                                       preparedStmt->oci_error,
2889                                       (sb4) day,
2890                                       (sb4) hour,
2891                                       (sb4) minute,
2892                                       (sb4) second,
2893                                       (sb4) micro_second,
2894                                       (OCIInterval *) param->descriptor) != OCI_SUCCESS) {
2895             logError(printf("sqlBindDuration: OCIIntervalSetDaySecond:\n");
2896                      printError(preparedStmt->oci_error););
2897             err_info = RANGE_ERROR;
2898           } /* if */
2899         } /* if */
2900       } /* if */
2901       if (unlikely(err_info != OKAY_NO_ERROR)) {
2902         raise_error(err_info);
2903       } else if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
2904                                        &param->bind_handle,
2905                                        preparedStmt->oci_error,
2906                                        (ub4) pos,
2907                                        param->buffer,
2908                                        (sb4) param->buffer_length,
2909                                        buffer_type,
2910                                        NULL, NULL, NULL, 0, NULL,
2911                                        OCI_DEFAULT) != OCI_SUCCESS))  {
2912         setDbErrorMsg("sqlBindDuration", "OCIBindByPos",
2913                       preparedStmt->oci_error);
2914         logError(printf("sqlBindDuration: OCIBindByPos:\n%s\n",
2915                         dbError.message););
2916         raise_error(DATABASE_ERROR);
2917       } else {
2918         preparedStmt->executeSuccessful = FALSE;
2919         preparedStmt->fetchOkay = FALSE;
2920         param->bound = TRUE;
2921       } /* if */
2922     } /* if */
2923   } /* sqlBindDuration */
2924 
2925 
2926 
sqlBindFloat(sqlStmtType sqlStatement,intType pos,floatType value)2927 static void sqlBindFloat (sqlStmtType sqlStatement, intType pos, floatType value)
2928 
2929   {
2930     preparedStmtType preparedStmt;
2931     bindDataType param;
2932 #ifdef SQLT_BFLOAT
2933 #if FLOATTYPE_SIZE == 32
2934     const uint16Type buffer_type = SQLT_BFLOAT;
2935 #elif FLOATTYPE_SIZE == 64
2936     const uint16Type buffer_type = SQLT_BDOUBLE;
2937 #endif
2938     const memSizeType buffer_length = sizeof(floatType);
2939 #else
2940     const uint16Type buffer_type = SQLT_NUM;
2941     const memSizeType buffer_length = SIZEOF_SQLT_NUM;
2942     int length;
2943 #endif
2944     errInfoType err_info = OKAY_NO_ERROR;
2945 
2946   /* sqlBindFloat */
2947     logFunction(printf("sqlBindFloat(" FMT_U_MEM ", " FMT_D ", " FMT_E ")\n",
2948                        (memSizeType) sqlStatement, pos, value););
2949     preparedStmt = (preparedStmtType) sqlStatement;
2950     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
2951       logError(printf("sqlBindFloat: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
2952                       pos, preparedStmt->param_array_size););
2953       raise_error(RANGE_ERROR);
2954     } else {
2955       param = &preparedStmt->param_array[pos - 1];
2956       if (param->buffer_capacity < buffer_length) {
2957         free(param->buffer);
2958         if ((param->buffer = malloc(buffer_length)) == NULL) {
2959           param->buffer_capacity = 0;
2960           err_info = MEMORY_ERROR;
2961         } else {
2962           param->buffer_capacity = buffer_length;
2963         } /* if */
2964       } /* if */
2965       if (unlikely(err_info != OKAY_NO_ERROR)) {
2966         raise_error(err_info);
2967       } else {
2968         param->buffer_type = buffer_type;
2969         param->buffer_length = buffer_length;
2970 #ifdef SQLT_BFLOAT
2971         *(floatType *) param->buffer = value;
2972         if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
2973                                   &param->bind_handle,
2974                                   preparedStmt->oci_error,
2975                                   (ub4) pos,
2976                                   param->buffer,
2977                                   sizeof(floatType),
2978                                   buffer_type, NULL, NULL, NULL, 0, NULL,
2979                                   OCI_DEFAULT) != OCI_SUCCESS)) {
2980           setDbErrorMsg("sqlBindFloat", "OCIBindByPos",
2981                         preparedStmt->oci_error);
2982           logError(printf("sqlBindFloat: OCIBindByPos:\n%s\n",
2983                           dbError.message););
2984           raise_error(DATABASE_ERROR);
2985         } else {
2986           preparedStmt->executeSuccessful = FALSE;
2987           preparedStmt->fetchOkay = FALSE;
2988           param->bound = TRUE;
2989         } /* if */
2990       } /* if */
2991 #else
2992         length = setFloat(param->buffer, value, &err_info);
2993         if (unlikely(err_info != OKAY_NO_ERROR)) {
2994           raise_error(err_info);
2995         } else {
2996           if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
2997                                     &param->bind_handle,
2998                                     preparedStmt->oci_error,
2999                                     (ub4) pos,
3000                                     param->buffer,
3001                                     length,
3002                                     SQLT_NUM, NULL, NULL, NULL, 0, NULL,
3003                                     OCI_DEFAULT) != OCI_SUCCESS)) {
3004             setDbErrorMsg("sqlBindFloat", "OCIBindByPos",
3005                           preparedStmt->oci_error);
3006             logError(printf("sqlBindFloat: OCIBindByPos:\n%s\n",
3007                             dbError.message););
3008             raise_error(DATABASE_ERROR);
3009           } else {
3010             preparedStmt->executeSuccessful = FALSE;
3011             preparedStmt->fetchOkay = FALSE;
3012             param->bound = TRUE;
3013           } /* if */
3014         } /* if */
3015       } /* if */
3016 #endif
3017     } /* if */
3018   } /* sqlBindFloat */
3019 
3020 
3021 
sqlBindInt(sqlStmtType sqlStatement,intType pos,intType value)3022 static void sqlBindInt (sqlStmtType sqlStatement, intType pos, intType value)
3023 
3024   {
3025     preparedStmtType preparedStmt;
3026     bindDataType param;
3027     errInfoType err_info = OKAY_NO_ERROR;
3028 
3029   /* sqlBindInt */
3030     logFunction(printf("sqlBindInt(" FMT_U_MEM ", " FMT_D ", " FMT_D ")\n",
3031                        (memSizeType) sqlStatement, pos, value););
3032     preparedStmt = (preparedStmtType) sqlStatement;
3033     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3034       logError(printf("sqlBindInt: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3035                       pos, preparedStmt->param_array_size););
3036       raise_error(RANGE_ERROR);
3037     } else {
3038       param = &preparedStmt->param_array[pos - 1];
3039       if (param->buffer_capacity < sizeof(int64Type)) {
3040         free(param->buffer);
3041         if ((param->buffer = malloc(sizeof(int64Type))) == NULL) {
3042           param->buffer_capacity = 0;
3043           err_info = MEMORY_ERROR;
3044         } else {
3045           param->buffer_capacity = sizeof(int64Type);
3046         } /* if */
3047       } /* if */
3048       if (unlikely(err_info != OKAY_NO_ERROR)) {
3049         raise_error(err_info);
3050       } else {
3051         param->buffer_type = SQLT_INT;
3052         param->buffer_length = sizeof(int64Type);
3053         *(int64Type *) param->buffer = (int64Type) value;
3054         if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
3055                                   &param->bind_handle,
3056                                   preparedStmt->oci_error,
3057                                   (ub4) pos,
3058                                   param->buffer,
3059                                   sizeof(int64Type),
3060                                   SQLT_INT, NULL, NULL, NULL, 0, NULL,
3061                                   OCI_DEFAULT) != OCI_SUCCESS)) {
3062           setDbErrorMsg("sqlBindInt", "OCIBindByPos",
3063                         preparedStmt->oci_error);
3064           logError(printf("sqlBindInt: OCIBindByPos:\n%s\n",
3065                           dbError.message););
3066           raise_error(DATABASE_ERROR);
3067         } else {
3068           preparedStmt->executeSuccessful = FALSE;
3069           preparedStmt->fetchOkay = FALSE;
3070           param->bound = TRUE;
3071         } /* if */
3072       } /* if */
3073     } /* if */
3074   } /* sqlBindInt */
3075 
3076 
3077 
sqlBindNull(sqlStmtType sqlStatement,intType pos)3078 static void sqlBindNull (sqlStmtType sqlStatement, intType pos)
3079 
3080   {
3081     preparedStmtType preparedStmt;
3082     bindDataType param;
3083 
3084   /* sqlBindNull */
3085     logFunction(printf("sqlBindNull(" FMT_U_MEM ", " FMT_D ")\n",
3086                        (memSizeType) sqlStatement, pos););
3087     preparedStmt = (preparedStmtType) sqlStatement;
3088     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3089       logError(printf("sqlBindNull: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3090                       pos, preparedStmt->param_array_size););
3091       raise_error(RANGE_ERROR);
3092     } else {
3093       param = &preparedStmt->param_array[pos - 1];
3094       param->indicator = -1;
3095       if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
3096                                 &param->bind_handle,
3097                                 preparedStmt->oci_error,
3098                                 (ub4) pos,
3099                                 NULL,
3100                                 0,
3101                                 SQLT_CHR,
3102                                 &param->indicator,
3103                                 NULL, NULL, 0, NULL,
3104                                 OCI_DEFAULT) != OCI_SUCCESS)) {
3105         setDbErrorMsg("sqlBindNull", "OCIBindByPos",
3106                       preparedStmt->oci_error);
3107         logError(printf("sqlBindNull: OCIBindByPos:\n%s\n",
3108                         dbError.message););
3109         raise_error(DATABASE_ERROR);
3110       } else {
3111         preparedStmt->executeSuccessful = FALSE;
3112         preparedStmt->fetchOkay = FALSE;
3113         param->bound = TRUE;
3114       } /* if */
3115     } /* if */
3116   } /* sqlBindNull */
3117 
3118 
3119 
sqlBindStri(sqlStmtType sqlStatement,intType pos,const const_striType stri)3120 static void sqlBindStri (sqlStmtType sqlStatement, intType pos,
3121     const const_striType stri)
3122 
3123   {
3124     preparedStmtType preparedStmt;
3125     bindDataType param;
3126     cstriType stri8;
3127     cstriType resized_stri8;
3128     memSizeType length;
3129 
3130   /* sqlBindStri */
3131     logFunction(printf("sqlBindStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
3132                        (memSizeType) sqlStatement, pos, striAsUnquotedCStri(stri)););
3133     preparedStmt = (preparedStmtType) sqlStatement;
3134     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3135       logError(printf("sqlBindStri: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3136                       pos, preparedStmt->param_array_size););
3137       raise_error(RANGE_ERROR);
3138     } else {
3139       param = &preparedStmt->param_array[pos - 1];
3140       stri8 = stri_to_cstri8_buf(stri, &length);
3141       if (unlikely(stri8 == NULL)) {
3142         raise_error(MEMORY_ERROR);
3143       } else if (unlikely(length > INT32TYPE_MAX)) {
3144         /* It is not possible to cast length to sb4. */
3145         free(stri8);
3146         raise_error(MEMORY_ERROR);
3147       } else {
3148         resized_stri8 = REALLOC_CSTRI(stri8, length);
3149         if (likely(resized_stri8 != NULL)) {
3150           stri8 = resized_stri8;
3151         } /* if */
3152         free(param->buffer);
3153         /* For the buffer_type SQLT_CHR trailing blanks are stripped */
3154         /* and the resulting value is passed to the database.        */
3155         /* For the buffer_type SQLT_AFC the entire contents of the   */
3156         /* buffer (param->buffer_length) is passed to the database,  */
3157         /* including any trailing blanks or NULLs.                   */
3158         /* SQLT_AFC is used to keep trailing blanks and NULLs.       */
3159         param->buffer_type = SQLT_AFC;
3160         param->buffer_length = length;
3161         param->buffer_capacity = length;
3162         param->buffer = stri8;
3163         if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
3164                                   &param->bind_handle,
3165                                   preparedStmt->oci_error,
3166                                   (ub4) pos,
3167                                   param->buffer,
3168                                   (sb4) param->buffer_length,
3169                                   SQLT_AFC,
3170                                   NULL, NULL, NULL, 0, NULL,
3171                                   OCI_DEFAULT) != OCI_SUCCESS))  {
3172           setDbErrorMsg("sqlBindStri", "OCIBindByPos",
3173                         preparedStmt->oci_error);
3174           logError(printf("sqlBindStri: OCIBindByPos:\n%s\n",
3175                           dbError.message););
3176           raise_error(DATABASE_ERROR);
3177         } else {
3178           preparedStmt->executeSuccessful = FALSE;
3179           preparedStmt->fetchOkay = FALSE;
3180           param->bound = TRUE;
3181         } /* if */
3182       } /* if */
3183     } /* if */
3184   } /* sqlBindStri */
3185 
3186 
3187 
sqlBindTime(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second,intType time_zone)3188 static void sqlBindTime (sqlStmtType sqlStatement, intType pos,
3189     intType year, intType month, intType day, intType hour,
3190     intType minute, intType second, intType micro_second,
3191     intType time_zone)
3192 
3193   {
3194     preparedStmtType preparedStmt;
3195     bindDataType param;
3196     char timezoneStri[3 + 2 * INTTYPE_DECIMAL_SIZE + NULL_TERMINATION_LEN];
3197     memSizeType timezoneStriLength;
3198     errInfoType err_info = OKAY_NO_ERROR;
3199 
3200   /* sqlBindTime */
3201     logFunction(printf("sqlBindTime(" FMT_U_MEM ", " FMT_D ", "
3202                        F_D(04) "-" F_D(02) "-" F_D(02) " "
3203                        F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ", "
3204                        FMT_D ")\n",
3205                        (memSizeType) sqlStatement, pos,
3206                        year, month, day,
3207                        hour, minute, second, micro_second,
3208                        time_zone););
3209     preparedStmt = (preparedStmtType) sqlStatement;
3210     if (unlikely(pos < 1 || (uintType) pos > preparedStmt->param_array_size)) {
3211       logError(printf("sqlBindTime: pos: " FMT_D ", max pos: " FMT_U_MEM ".\n",
3212                       pos, preparedStmt->param_array_size););
3213       raise_error(RANGE_ERROR);
3214     } else if (unlikely(year <= INT16TYPE_MIN || year > INT16TYPE_MAX || month < 1 || month > 12 ||
3215                         day < 1 || day > 31 || hour < 0 || hour >= 24 ||
3216                         minute < 0 || minute >= 60 || second < 0 || second >= 60 ||
3217                         micro_second < 0 || micro_second >= 1000000)) {
3218       logError(printf("sqlBindTime: Time not in allowed range.\n"););
3219       raise_error(RANGE_ERROR);
3220     } else {
3221       param = &preparedStmt->param_array[pos - 1];
3222       if (param->buffer_capacity < sizeof(void *)) {
3223         free(param->buffer);
3224         if ((param->buffer = malloc(sizeof(void *))) == NULL) {
3225           param->buffer_capacity = 0;
3226           err_info = MEMORY_ERROR;
3227         } else {
3228           param->buffer_capacity = sizeof(void *);
3229         } /* if */
3230       } /* if */
3231       if (likely(err_info == OKAY_NO_ERROR)) {
3232         if (param->buffer_type != SQLT_TIMESTAMP_TZ && param->descriptor != NULL) {
3233           freeDescriptor(preparedStmt,
3234                          param->descriptor,
3235                          param->buffer_type);
3236           param->descriptor = NULL;
3237         } /* if */
3238         if (param->descriptor == NULL) {
3239           if (OCIDescriptorAlloc(preparedStmt->oci_environment,
3240                                  &param->descriptor,
3241                                  OCI_DTYPE_TIMESTAMP_TZ,  /* TIMESTAMP WITH TIME ZONE */
3242                                  0, NULL) != OCI_SUCCESS) {
3243             logError(printf("sqlBindTime: OCIDescriptorAlloc: Out of memory.\n"););
3244             err_info = MEMORY_ERROR;
3245           } /* if */
3246         } /* if */
3247       } /* if */
3248       if (likely(err_info == OKAY_NO_ERROR)) {
3249         *(void **) param->buffer = param->descriptor;
3250         param->buffer_type   = SQLT_TIMESTAMP_TZ;
3251         param->buffer_length = 0;
3252       } /* if */
3253       if (year <= 0) {
3254         /* In the database BC dates are represented with negative numbers */
3255         /* and the year 0 does not exist. The year 0 of the proleptic     */
3256         /* Gregorian calendar corresponds to 1 BC (= -1) in the database. */
3257         year--;
3258       } /* if */
3259       if (time_zone < 0) {
3260         if (unlikely(year == -1 && month == 12 && day == 31 &&
3261                      (hour + (-time_zone) / 60 > 23 ||
3262                      (hour + (-time_zone) / 60 == 23 &&
3263                      minute + (-time_zone) % 60 > 59)))) {
3264           /* When the time_zone would move the year from 1 BC to 1 AD the */
3265           /* function OCIDateTimeConstruct() fails. This is avoided by    */
3266           /* setting time_zone to zero. Luckily all time values at the    */
3267           /* default date 0-1-1 are not affected by this special case.    */
3268           time_zone = 0;
3269           /* printf(F_D(04) "-" F_D(02) "-" F_D(02) " "
3270                  F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ", " FMT_D "\n",
3271                  year, month, day, hour, minute, second, micro_second, time_zone); */
3272         } /* if */
3273         timezoneStriLength =
3274             (memSizeType) sprintf(timezoneStri, "-" F_D(02) ":" F_D(02),
3275                                   (-time_zone) / 60, (-time_zone) % 60);
3276       } else {
3277         if (unlikely((year == 1 || year == -4712) && month == 1 && day == 1 &&
3278                      (time_zone / 60 > hour ||
3279                      (time_zone / 60 == hour && time_zone % 60 > minute)))) {
3280           /* When the time_zone would move the year from 1 AD to 1 BC the */
3281           /* function OCIDateTimeConstruct() fails. This is avoided by    */
3282           /* setting time_zone to zero. For the minimum allowed time      */
3283           /* (January 1, 4712 BC) OCIDateTimeConstruct() does also not    */
3284           /* work correct, if the time_zone is greater than zero.         */
3285           time_zone = 0;
3286           /* printf(F_D(04) "-" F_D(02) "-" F_D(02) " "
3287                  F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ", " FMT_D "\n",
3288                  year, month, day, hour, minute, second, micro_second, time_zone); */
3289         } /* if */
3290         timezoneStriLength =
3291             (memSizeType) sprintf(timezoneStri, F_D(02) ":" F_D(02),
3292                                   time_zone / 60, time_zone % 60);
3293       } /* if */
3294       /* printf("timezone: %s\n", timezoneStri); */
3295       if (unlikely(err_info != OKAY_NO_ERROR)) {
3296         raise_error(err_info);
3297       } else if (unlikely(OCIDateTimeConstruct(preparedStmt->oci_environment,
3298                                                preparedStmt->oci_error,
3299                                                (OCIDateTime *) param->descriptor,
3300                                                (sb2) year, (ub1) month, (ub1) day,
3301                                                (ub1) hour, (ub1) minute, (ub1) second,
3302                                                (ub4) (micro_second * 1000),
3303                                                (OraText *) timezoneStri,
3304                                                timezoneStriLength) != OCI_SUCCESS)) {
3305         logError(printf("sqlBindTime: OCIDateTimeConstruct:\n");
3306                  printError(preparedStmt->oci_error););
3307         raise_error(RANGE_ERROR);
3308       } else if (unlikely(OCIBindByPos(preparedStmt->ppStmt,
3309                                        &param->bind_handle,
3310                                        preparedStmt->oci_error,
3311                                        (ub4) pos,
3312                                        param->buffer,
3313                                        (sb4) param->buffer_length,
3314                                        SQLT_TIMESTAMP_TZ,
3315                                        NULL, NULL, NULL, 0, NULL,
3316                                        OCI_DEFAULT) != OCI_SUCCESS))  {
3317         setDbErrorMsg("sqlBindTime", "OCIBindByPos",
3318                       preparedStmt->oci_error);
3319         logError(printf("sqlBindTime: OCIBindByPos:\n%s\n",
3320                         dbError.message););
3321         raise_error(DATABASE_ERROR);
3322       } else {
3323         preparedStmt->executeSuccessful = FALSE;
3324         preparedStmt->fetchOkay = FALSE;
3325         param->bound = TRUE;
3326       } /* if */
3327     } /* if */
3328   } /* sqlBindTime */
3329 
3330 
3331 
sqlClose(databaseType database)3332 static void sqlClose (databaseType database)
3333 
3334   {
3335     dbType db;
3336 
3337   /* sqlClose */
3338     db = (dbType) database;
3339     if (db->oci_service_context != NULL &&
3340         db->oci_error != NULL &&
3341         db->oci_session != NULL) {
3342       OCISessionEnd(db->oci_service_context, db->oci_error,
3343                     db->oci_session, OCI_DEFAULT);
3344     } /* if */
3345     if (db->oci_server != NULL &&
3346         db->oci_error != NULL) {
3347       OCIServerDetach(db->oci_server, db->oci_error,
3348                       OCI_DEFAULT);
3349     } /* if */
3350     if (db->oci_session != NULL) {
3351       OCIHandleFree(db->oci_session, OCI_HTYPE_SESSION);
3352       db->oci_session = NULL;
3353     } /* if */
3354     if (db->oci_service_context != NULL) {
3355       OCIHandleFree(db->oci_service_context, OCI_HTYPE_SVCCTX);
3356       db->oci_service_context = NULL;
3357     } /* if */
3358     if (db->oci_server != NULL) {
3359       OCIHandleFree(db->oci_server, OCI_HTYPE_SERVER);
3360       db->oci_server = NULL;
3361     } /* if */
3362     if (db->oci_error != NULL) {
3363       OCIHandleFree(db->oci_error, OCI_HTYPE_ERROR);
3364       db->oci_error = NULL;
3365     } /* if */
3366     if (db->oci_environment != NULL) {
3367       OCIHandleFree(db->oci_environment, OCI_HTYPE_ENV);
3368       db->oci_environment = NULL;
3369     } /* if */
3370   } /* sqlClose */
3371 
3372 
3373 
sqlColumnBigInt(sqlStmtType sqlStatement,intType column)3374 static bigIntType sqlColumnBigInt (sqlStmtType sqlStatement, intType column)
3375 
3376   {
3377     preparedStmtType preparedStmt;
3378     resultDataType columnData;
3379     bigIntType columnValue;
3380 
3381   /* sqlColumnBigInt */
3382     logFunction(printf("sqlColumnBigInt(" FMT_U_MEM ", " FMT_D ")\n",
3383                        (memSizeType) sqlStatement, column););
3384     preparedStmt = (preparedStmtType) sqlStatement;
3385     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3386                  (uintType) column > preparedStmt->result_array_size)) {
3387       logError(printf("sqlColumnBigInt: Fetch okay: %d, column: " FMT_D
3388                       ", max column: " FMT_U_MEM ".\n",
3389                       preparedStmt->fetchOkay, column,
3390                       preparedStmt->result_array_size););
3391       raise_error(RANGE_ERROR);
3392       columnValue = NULL;
3393     } else {
3394       columnData = &preparedStmt->result_array[column - 1];
3395       if (columnData->indicator == -1) {
3396         /* printf("Column is NULL -> Use default value: 0\n"); */
3397         columnValue = bigZero();
3398       } else if (unlikely(columnData->indicator != 0)) {
3399         dbInconsistent("sqlColumnBigInt", "OCIDefineByPos");
3400         logError(printf("sqlColumnBigInt: Column " FMT_D " has indicator: %d\n",
3401                         column, columnData->indicator););
3402         raise_error(DATABASE_ERROR);
3403         columnValue = NULL;
3404       } else {
3405         /* printf("buffer_type: %s\n",
3406            nameOfBufferType(columnData->buffer_type)); */
3407         switch (columnData->buffer_type) {
3408           case SQLT_NUM:
3409             columnValue = getBigInt(columnData->buffer, columnData->length);
3410             break;
3411           default:
3412             logError(printf("sqlColumnBigInt: Column " FMT_D " has the unknown type %s.\n",
3413                             column, nameOfBufferType(columnData->buffer_type)););
3414             raise_error(RANGE_ERROR);
3415             columnValue = NULL;
3416             break;
3417         } /* switch */
3418       } /* if */
3419     } /* if */
3420     logFunction(printf("sqlColumnBigInt --> %s\n", bigHexCStri(columnValue)););
3421     return columnValue;
3422   } /* sqlColumnBigInt */
3423 
3424 
3425 
sqlColumnBigRat(sqlStmtType sqlStatement,intType column,bigIntType * numerator,bigIntType * denominator)3426 static void sqlColumnBigRat (sqlStmtType sqlStatement, intType column,
3427     bigIntType *numerator, bigIntType *denominator)
3428 
3429   {
3430     preparedStmtType preparedStmt;
3431     resultDataType columnData;
3432 
3433   /* sqlColumnBigRat */
3434     logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", *, *)\n",
3435                        (memSizeType) sqlStatement, column););
3436     preparedStmt = (preparedStmtType) sqlStatement;
3437     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3438                  (uintType) column > preparedStmt->result_array_size)) {
3439       logError(printf("sqlColumnBigRat: Fetch okay: %d, column: " FMT_D
3440                       ", max column: " FMT_U_MEM ".\n",
3441                       preparedStmt->fetchOkay, column,
3442                       preparedStmt->result_array_size););
3443       raise_error(RANGE_ERROR);
3444     } else {
3445       columnData = &preparedStmt->result_array[column - 1];
3446       if (columnData->indicator == -1) {
3447         /* printf("Column is NULL -> Use default value: 0\n"); */
3448         *numerator = bigZero();
3449         *denominator = bigFromInt32(1);
3450       } else if (unlikely(columnData->indicator != 0)) {
3451         dbInconsistent("sqlColumnBigRat", "OCIDefineByPos");
3452         logError(printf("sqlColumnBigRat: Column " FMT_D " has indicator: %d\n",
3453                         column, columnData->indicator););
3454         raise_error(DATABASE_ERROR);
3455       } else {
3456         /* printf("buffer_type: %s\n",
3457            nameOfBufferType(columnData->buffer_type)); */
3458         switch (columnData->buffer_type) {
3459           case SQLT_NUM:
3460             *numerator = getBigRational(columnData->buffer,
3461                                         columnData->length,
3462                                         denominator);
3463             break;
3464           default:
3465             logError(printf("sqlColumnBigRat: Column " FMT_D " has the unknown type %s.\n",
3466                             column, nameOfBufferType(columnData->buffer_type)););
3467             raise_error(RANGE_ERROR);
3468             break;
3469         } /* switch */
3470       } /* if */
3471     } /* if */
3472     logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s) -->\n",
3473                        (memSizeType) sqlStatement, column,
3474                        bigHexCStri(*numerator), bigHexCStri(*denominator)););
3475   } /* sqlColumnBigRat */
3476 
3477 
3478 
sqlColumnBool(sqlStmtType sqlStatement,intType column)3479 static boolType sqlColumnBool (sqlStmtType sqlStatement, intType column)
3480 
3481   {
3482     preparedStmtType preparedStmt;
3483     resultDataType columnData;
3484     intType columnValue;
3485 
3486   /* sqlColumnBool */
3487     logFunction(printf("sqlColumnBool(" FMT_U_MEM ", " FMT_D ")\n",
3488                        (memSizeType) sqlStatement, column););
3489     preparedStmt = (preparedStmtType) sqlStatement;
3490     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3491                  (uintType) column > preparedStmt->result_array_size)) {
3492       logError(printf("sqlColumnBool: Fetch okay: %d, column: " FMT_D
3493                       ", max column: " FMT_U_MEM ".\n",
3494                       preparedStmt->fetchOkay, column,
3495                       preparedStmt->result_array_size););
3496       raise_error(RANGE_ERROR);
3497       columnValue = 0;
3498     } else {
3499       columnData = &preparedStmt->result_array[column - 1];
3500       if (columnData->indicator == -1) {
3501         /* printf("Column is NULL -> Use default value: FALSE\n"); */
3502         columnValue = 0;
3503       } else if (unlikely(columnData->indicator != 0)) {
3504         dbInconsistent("sqlColumnBool", "OCIDefineByPos");
3505         logError(printf("sqlColumnBool: Column " FMT_D " has indicator: %d\n",
3506                         column, columnData->indicator););
3507         raise_error(DATABASE_ERROR);
3508         columnValue = 0;
3509       } else {
3510         /* printf("buffer_type: %s\n",
3511            nameOfBufferType(columnData->buffer_type)); */
3512         switch (columnData->buffer_type) {
3513           case SQLT_CHR: /* VARCHAR2 */
3514           case SQLT_VCS: /* VARCHAR */
3515           case SQLT_AFC: /* CHAR */
3516             if (unlikely(columnData->length != 1)) {
3517               logError(printf("sqlColumnBool: Column " FMT_D ": "
3518                               "The size of a boolean field must be 1.\n", column););
3519               raise_error(RANGE_ERROR);
3520               columnValue = 0;
3521             } else {
3522               columnValue = *(const_cstriType) columnData->buffer - '0';
3523             } /* if */
3524             break;
3525           case SQLT_NUM:
3526             columnValue = getInt(columnData->buffer, columnData->length);
3527             break;
3528           default:
3529             logError(printf("sqlColumnBool: Column " FMT_D " has the unknown type %s.\n",
3530                             column, nameOfBufferType(columnData->buffer_type)););
3531             raise_error(RANGE_ERROR);
3532             columnValue = 0;
3533             break;
3534         } /* switch */
3535         if (unlikely((uintType) columnValue >= 2)) {
3536           logError(printf("sqlColumnBool: Boolean value " FMT_D " not in allowed range.\n",
3537                           columnValue););
3538           raise_error(RANGE_ERROR);
3539         } /* if */
3540       } /* if */
3541     } /* if */
3542     logFunction(printf("sqlColumnBool --> %s\n", columnValue ? "TRUE" : "FALSE"););
3543     return columnValue != 0;
3544   } /* sqlColumnBool */
3545 
3546 
3547 
sqlColumnBStri(sqlStmtType sqlStatement,intType column)3548 static bstriType sqlColumnBStri (sqlStmtType sqlStatement, intType column)
3549 
3550   {
3551     preparedStmtType preparedStmt;
3552     resultDataType columnData;
3553     memSizeType length;
3554     errInfoType err_info = OKAY_NO_ERROR;
3555     bstriType columnValue;
3556 
3557   /* sqlColumnBStri */
3558     logFunction(printf("sqlColumnBStri(" FMT_U_MEM ", " FMT_D ")\n",
3559                        (memSizeType) sqlStatement, column););
3560     preparedStmt = (preparedStmtType) sqlStatement;
3561     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3562                  (uintType) column > preparedStmt->result_array_size)) {
3563       logError(printf("sqlColumnBStri: Fetch okay: %d, column: " FMT_D
3564                       ", max column: " FMT_U_MEM ".\n",
3565                       preparedStmt->fetchOkay, column,
3566                       preparedStmt->result_array_size););
3567       raise_error(RANGE_ERROR);
3568       columnValue = NULL;
3569     } else {
3570       columnData = &preparedStmt->result_array[column - 1];
3571       if (columnData->indicator == -1) {
3572         /* printf("Column is NULL -> Use default value: \"\"\n"); */
3573         if (unlikely(!ALLOC_BSTRI_SIZE_OK(columnValue, 0))) {
3574           raise_error(MEMORY_ERROR);
3575         } else {
3576           columnValue->size = 0;
3577         } /* if */
3578       } else if (unlikely(columnData->indicator != 0)) {
3579         dbInconsistent("sqlColumnBStri", "OCIDefineByPos");
3580         logError(printf("sqlColumnBStri: Column " FMT_D " has indicator: %d\n",
3581                         column, columnData->indicator););
3582         raise_error(DATABASE_ERROR);
3583         columnValue = NULL;
3584       } else {
3585         /* printf("buffer_type: %s\n",
3586            nameOfBufferType(columnData->buffer_type)); */
3587         switch (columnData->buffer_type) {
3588           case SQLT_BIN: /* RAW */
3589           case SQLT_VBI: /* VARRAW */
3590           case SQLT_LBI: /* LONG RAW */
3591           case SQLT_LVB: /* LONG VARRAW */
3592             length = columnData->length;
3593             if (unlikely(!ALLOC_BSTRI_CHECK_SIZE(columnValue, length))) {
3594               raise_error(MEMORY_ERROR);
3595             } else {
3596               columnValue->size = length;
3597               memcpy(columnValue->mem, (ustriType) columnData->buffer, length);
3598             } /* if */
3599             break;
3600           case SQLT_BLOB: /* Binary LOB */
3601           case SQLT_FILE: /* Binary FILE */
3602             columnValue = getBlob(preparedStmt,
3603                                   (OCILobLocator *) columnData->descriptor,
3604                                   &err_info);
3605             if (unlikely(columnValue == NULL)) {
3606               raise_error(err_info);
3607             } /* if */
3608             break;
3609           default:
3610             logError(printf("sqlColumnBStri: Column " FMT_D " has the unknown type %s.\n",
3611                             column, nameOfBufferType(columnData->buffer_type)););
3612             raise_error(RANGE_ERROR);
3613             columnValue = NULL;
3614             break;
3615         } /* switch */
3616       } /* if */
3617     } /* if */
3618     logFunction(printf("sqlColumnBStri --> \"%s\"\n", bstriAsUnquotedCStri(columnValue)););
3619     return columnValue;
3620   } /* sqlColumnBStri */
3621 
3622 
3623 
sqlColumnDuration(sqlStmtType sqlStatement,intType column,intType * year,intType * month,intType * day,intType * hour,intType * minute,intType * second,intType * micro_second)3624 static void sqlColumnDuration (sqlStmtType sqlStatement, intType column,
3625     intType *year, intType *month, intType *day, intType *hour,
3626     intType *minute, intType *second, intType *micro_second)
3627 
3628   {
3629     preparedStmtType preparedStmt;
3630     resultDataType columnData;
3631     sb4 ociYear;
3632     sb4 ociMonth;
3633     sb4 ociDay;
3634     sb4 ociHour;
3635     sb4 ociMinute;
3636     sb4 ociSecond;
3637     sb4 ociFsec;
3638     errInfoType err_info = OKAY_NO_ERROR;
3639 
3640   /* sqlColumnDuration */
3641     logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ", *)\n",
3642                        (memSizeType) sqlStatement, column););
3643     preparedStmt = (preparedStmtType) sqlStatement;
3644     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3645                  (uintType) column > preparedStmt->result_array_size)) {
3646       logError(printf("sqlColumnDuration: Fetch okay: %d, column: " FMT_D
3647                       ", max column: " FMT_U_MEM ".\n",
3648                       preparedStmt->fetchOkay, column,
3649                       preparedStmt->result_array_size););
3650       raise_error(RANGE_ERROR);
3651     } else {
3652       columnData = &preparedStmt->result_array[column - 1];
3653       if (columnData->indicator == -1) {
3654         /* printf("Column is NULL -> Use default value: P0D\n"); */
3655         *year         = 0;
3656         *month        = 0;
3657         *day          = 0;
3658         *hour         = 0;
3659         *minute       = 0;
3660         *second       = 0;
3661         *micro_second = 0;
3662       } else if (columnData->indicator != 0) {
3663         dbInconsistent("sqlColumnDuration", "OCIDefineByPos");
3664         logError(printf("sqlColumnDuration: Column " FMT_D " has indicator: %d\n",
3665                         column, columnData->indicator););
3666         err_info = DATABASE_ERROR;
3667       } else {
3668         /* printf("buffer_type: %s\n",
3669            nameOfBufferType(columnData->buffer_type)); */
3670         switch (columnData->buffer_type) {
3671           case SQLT_INTERVAL_YM:
3672             /* printf("SQLT_INTERVAL_YM\n"); */
3673             if (unlikely(OCIIntervalGetYearMonth(preparedStmt->oci_environment,
3674                                                  preparedStmt->oci_error,
3675                                                  &ociYear,
3676                                                  &ociMonth,
3677                                                  (OCIInterval *) columnData->descriptor) != OCI_SUCCESS)) {
3678               logError(printf("sqlColumnDuration: OCIIntervalGetYearMonth:\n");
3679                        printError(preparedStmt->oci_error););
3680               raise_error(RANGE_ERROR);
3681             } else {
3682               *year   = ociYear;
3683               *month  = ociMonth;
3684               *day    = 0;
3685               *hour   = 0;
3686               *minute = 0;
3687               *second = 0;
3688               *micro_second = 0;
3689             } /* if */
3690             break;
3691           case SQLT_INTERVAL_DS:
3692             /* printf("SQLT_INTERVAL_DS\n"); */
3693             if (unlikely(OCIIntervalGetDaySecond(preparedStmt->oci_environment,
3694                                                  preparedStmt->oci_error,
3695                                                  &ociDay,
3696                                                  &ociHour,
3697                                                  &ociMinute,
3698                                                  &ociSecond,
3699                                                  &ociFsec,
3700                                                  (OCIInterval *) columnData->descriptor) != OCI_SUCCESS)) {
3701               logError(printf("sqlColumnDuration: OCIIntervalGetDaySecond:\n");
3702                        printError(preparedStmt->oci_error););
3703               raise_error(RANGE_ERROR);
3704             } else {
3705               *year   = 0;
3706               *month  = 0;
3707               *day    = ociDay;
3708               *hour   = ociHour;
3709               *minute = ociMinute;
3710               *second = ociSecond;
3711               *micro_second = ociFsec;
3712             } /* if */
3713             break;
3714           default:
3715             logError(printf("sqlColumnDuration: Column " FMT_D " has the unknown type %s.\n",
3716                             column, nameOfBufferType(columnData->buffer_type)););
3717             err_info = RANGE_ERROR;
3718             break;
3719         } /* switch */
3720         if (unlikely(err_info != OKAY_NO_ERROR)) {
3721           raise_error(err_info);
3722         } /* if */
3723       } /* if */
3724     } /* if */
3725     logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ") -> P"
3726                                             FMT_D "Y" FMT_D "M" FMT_D "DT"
3727                                             FMT_D "H" FMT_D "M%s" FMT_U "." F_U(06) "S\n",
3728                        (memSizeType) sqlStatement, column,
3729                        *year, *month, *day, *hour, *minute,
3730                        *second < 0 || *micro_second < 0 ? "-" : "",
3731                        intAbs(*second), intAbs(*micro_second)););
3732   } /* sqlColumnDuration */
3733 
3734 
3735 
sqlColumnFloat(sqlStmtType sqlStatement,intType column)3736 static floatType sqlColumnFloat (sqlStmtType sqlStatement, intType column)
3737 
3738   {
3739     preparedStmtType preparedStmt;
3740     resultDataType columnData;
3741     floatType columnValue;
3742 
3743   /* sqlColumnFloat */
3744     logFunction(printf("sqlColumnFloat(" FMT_U_MEM ", " FMT_D ")\n",
3745                        (memSizeType) sqlStatement, column););
3746     preparedStmt = (preparedStmtType) sqlStatement;
3747     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3748                  (uintType) column > preparedStmt->result_array_size)) {
3749       logError(printf("sqlColumnFloat: Fetch okay: %d, column: " FMT_D
3750                       ", max column: " FMT_U_MEM ".\n",
3751                       preparedStmt->fetchOkay, column,
3752                       preparedStmt->result_array_size););
3753       raise_error(RANGE_ERROR);
3754       columnValue = 0.0;
3755     } else {
3756       columnData = &preparedStmt->result_array[column - 1];
3757       if (columnData->indicator == -1) {
3758         /* printf("Column is NULL -> Use default value: 0.0\n"); */
3759         columnValue = 0.0;
3760       } else if (unlikely(columnData->indicator != 0)) {
3761         dbInconsistent("sqlColumnFloat", "OCIDefineByPos");
3762         logError(printf("sqlColumnFloat: Column " FMT_D " has indicator: %d\n",
3763                         column, columnData->indicator););
3764         raise_error(DATABASE_ERROR);
3765         columnValue = 0.0;
3766       } else {
3767         /* printf("buffer_type: %s\n",
3768            nameOfBufferType(columnData->buffer_type)); */
3769         switch (columnData->buffer_type) {
3770           case SQLT_BFLOAT:
3771             columnValue = *(float *) columnData->buffer;
3772             break;
3773           case SQLT_BDOUBLE:
3774             columnValue = *(double *) columnData->buffer;
3775             break;
3776           case SQLT_NUM:
3777             columnValue = getFloat(columnData->buffer, columnData->length);
3778             break;
3779           default:
3780             logError(printf("sqlColumnFloat: Column " FMT_D " has the unknown type %s.\n",
3781                             column, nameOfBufferType(columnData->buffer_type)););
3782             raise_error(RANGE_ERROR);
3783             columnValue = 0.0;
3784             break;
3785         } /* switch */
3786       } /* if */
3787     } /* if */
3788     logFunction(printf("sqlColumnFloat --> " FMT_E "\n", columnValue););
3789     return columnValue;
3790   } /* sqlColumnFloat */
3791 
3792 
3793 
sqlColumnInt(sqlStmtType sqlStatement,intType column)3794 static intType sqlColumnInt (sqlStmtType sqlStatement, intType column)
3795 
3796   {
3797     preparedStmtType preparedStmt;
3798     resultDataType columnData;
3799     intType columnValue;
3800 
3801   /* sqlColumnInt */
3802     logFunction(printf("sqlColumnInt(" FMT_U_MEM ", " FMT_D ")\n",
3803                        (memSizeType) sqlStatement, column););
3804     preparedStmt = (preparedStmtType) sqlStatement;
3805     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3806                  (uintType) column > preparedStmt->result_array_size)) {
3807       logError(printf("sqlColumnInt: Fetch okay: %d, column: " FMT_D
3808                       ", max column: " FMT_U_MEM ".\n",
3809                       preparedStmt->fetchOkay, column,
3810                       preparedStmt->result_array_size););
3811       raise_error(RANGE_ERROR);
3812       columnValue = 0;
3813     } else {
3814       columnData = &preparedStmt->result_array[column - 1];
3815       if (columnData->indicator == -1) {
3816         /* printf("Column is NULL -> Use default value: 0\n"); */
3817         columnValue = 0;
3818       } else if (unlikely(columnData->indicator != 0)) {
3819         dbInconsistent("sqlColumnInt", "OCIDefineByPos");
3820         logError(printf("sqlColumnInt: Column " FMT_D " has indicator: %d\n",
3821                         column, columnData->indicator););
3822         raise_error(DATABASE_ERROR);
3823         columnValue = 0;
3824       } else {
3825         /* printf("buffer_type: %s\n",
3826            nameOfBufferType(columnData->buffer_type)); */
3827         switch (columnData->buffer_type) {
3828           case SQLT_NUM:
3829             columnValue = getInt(columnData->buffer, columnData->length);
3830             break;
3831           default:
3832             logError(printf("sqlColumnInt: Column " FMT_D " has the unknown type %s.\n",
3833                             column, nameOfBufferType(columnData->buffer_type)););
3834             raise_error(RANGE_ERROR);
3835             columnValue = 0;
3836             break;
3837         } /* switch */
3838       } /* if */
3839     } /* if */
3840     logFunction(printf("sqlColumnInt --> " FMT_D "\n", columnValue););
3841     return columnValue;
3842   } /* sqlColumnInt */
3843 
3844 
3845 
sqlColumnStri(sqlStmtType sqlStatement,intType column)3846 static striType sqlColumnStri (sqlStmtType sqlStatement, intType column)
3847 
3848   {
3849     preparedStmtType preparedStmt;
3850     resultDataType columnData;
3851     const_cstriType stri8;
3852     memSizeType length;
3853     const_cstriType zeroPos;
3854     errInfoType err_info = OKAY_NO_ERROR;
3855     striType columnValue;
3856 
3857   /* sqlColumnStri */
3858     logFunction(printf("sqlColumnStri(" FMT_U_MEM ", " FMT_D ")\n",
3859                        (memSizeType) sqlStatement, column););
3860     preparedStmt = (preparedStmtType) sqlStatement;
3861     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
3862                  (uintType) column > preparedStmt->result_array_size)) {
3863       logError(printf("sqlColumnStri: Fetch okay: %d, column: " FMT_D
3864                       ", max column: " FMT_U_MEM ".\n",
3865                       preparedStmt->fetchOkay, column,
3866                       preparedStmt->result_array_size););
3867       raise_error(RANGE_ERROR);
3868       columnValue = NULL;
3869     } else {
3870       columnData = &preparedStmt->result_array[column - 1];
3871       if (columnData->indicator == -1) {
3872         /* printf("Column is NULL -> Use default value: \"\"\n"); */
3873         columnValue = strEmpty();
3874       } else if (unlikely(columnData->indicator != 0)) {
3875         dbInconsistent("sqlColumnStri", "OCIDefineByPos");
3876         logError(printf("sqlColumnStri: Column " FMT_D " has indicator: %d\n",
3877                         column, columnData->indicator););
3878         raise_error(DATABASE_ERROR);
3879         columnValue = NULL;
3880       } else {
3881         /* printf("buffer_type: %s\n",
3882            nameOfBufferType(columnData->buffer_type)); */
3883         switch (columnData->buffer_type) {
3884           case SQLT_CHR: /* VARCHAR2 */
3885           case SQLT_VCS: /* VARCHAR */
3886           case SQLT_LNG: /* LONG */
3887           case SQLT_LVC: /* LONG VARCHAR */
3888             stri8 = (cstriType) columnData->buffer;
3889             length = columnData->length;
3890             /* printf("length: " FMT_U_MEM "\n", length); */
3891             /* printf("buffer: \"");
3892                fwrite(stri8, 1, length, stdout);
3893                printf("\"\n"); */
3894             columnValue = cstri8_buf_to_stri(stri8, (memSizeType) length, &err_info);
3895             if (unlikely(columnValue == NULL)) {
3896               raise_error(err_info);
3897             } /* if */
3898             break;
3899           case SQLT_AFC: /* CHAR */
3900             stri8 = (cstriType) columnData->buffer;
3901             length = columnData->length;
3902             /* printf("buffer: \"");
3903                fwrite(stri8, 1, length, stdout);
3904                printf("\"\n"); */
3905             while (length > 0 && stri8[length - 1] == ' ') {
3906               length--;
3907             } /* if */
3908             columnValue = cstri8_buf_to_stri(stri8, (memSizeType) length, &err_info);
3909             if (unlikely(columnValue == NULL)) {
3910               raise_error(err_info);
3911             } /* if */
3912             break;
3913           case SQLT_STR: /* NULL-terminated STRING */
3914           case SQLT_AVC: /* CHARZ */
3915             stri8 = (cstriType) columnData->buffer;
3916             length = columnData->length;
3917             zeroPos = (const_cstriType) memchr(stri8, '\0', length);
3918             if (zeroPos != NULL) {
3919               length = (memSizeType) (zeroPos - stri8);
3920             } /* if */
3921             columnValue = cstri8_buf_to_stri(stri8, (memSizeType) length, &err_info);
3922             if (unlikely(columnValue == NULL)) {
3923               raise_error(err_info);
3924             } /* if */
3925             break;
3926           case SQLT_VST: /* OCI STRING type */
3927             stri8 = (cstriType) OCIStringPtr(preparedStmt->oci_environment,
3928                                              (OCIString *) columnData->buffer);
3929             if (unlikely(stri8 == NULL)) {
3930               dbInconsistent("sqlColumnStri", "OCIStringPtr");
3931               logError(printf("sqlColumnStri: Column " FMT_D ": "
3932                               "OCIStringPtr returned NULL.\n", column););
3933               raise_error(DATABASE_ERROR);
3934               columnValue = NULL;
3935             } else {
3936               length = OCIStringSize(preparedStmt->oci_environment,
3937                                      (OCIString *) columnData->buffer);
3938               columnValue = cstri8_buf_to_stri(stri8, (memSizeType) length, &err_info);
3939               if (unlikely(columnValue == NULL)) {
3940                 raise_error(err_info);
3941               } /* if */
3942             } /* if */
3943             break;
3944           case SQLT_CLOB: /* Character LOB  */
3945             columnValue = getClob(preparedStmt,
3946                                   (OCILobLocator *) columnData->descriptor,
3947                                   &err_info);
3948             if (unlikely(columnValue == NULL)) {
3949               raise_error(err_info);
3950             } /* if */
3951             break;
3952           case SQLT_BIN: /* RAW */
3953           case SQLT_VBI: /* VARRAW */
3954           case SQLT_LBI: /* LONG RAW */
3955           case SQLT_LVB: /* LONG VARRAW */
3956             columnValue = cstri_buf_to_stri((const_cstriType) columnData->buffer,
3957                                             columnData->length);
3958             if (unlikely(columnValue == NULL)) {
3959               raise_error(MEMORY_ERROR);
3960             } /* if */
3961             break;
3962           case SQLT_BLOB: /* Binary LOB */
3963           case SQLT_FILE: /* Binary FILE */
3964             columnValue = getBlobAsStri(preparedStmt,
3965                                         (OCILobLocator *) columnData->descriptor,
3966                                         &err_info);
3967             if (unlikely(columnValue == NULL)) {
3968               raise_error(err_info);
3969             } /* if */
3970             break;
3971           case SQLT_RDD: /* ROWID */
3972             columnValue = getRowid(preparedStmt,
3973                                    (OCIRowid *) columnData->descriptor,
3974                                    &err_info);
3975             if (unlikely(columnValue == NULL)) {
3976               raise_error(err_info);
3977             } /* if */
3978             break;
3979           case SQLT_REF:
3980             columnValue = getRef(preparedStmt,
3981                                  columnData->ref,
3982                                  &err_info);
3983             if (unlikely(columnValue == NULL)) {
3984               raise_error(err_info);
3985             } /* if */
3986             break;
3987           default:
3988             logError(printf("sqlColumnStri: Column " FMT_D " has the unknown type %s.\n",
3989                             column, nameOfBufferType(columnData->buffer_type)););
3990             raise_error(RANGE_ERROR);
3991             columnValue = NULL;
3992             break;
3993         } /* switch */
3994       } /* if */
3995     } /* if */
3996     logFunction(printf("sqlColumnStri --> \"%s\"\n", striAsUnquotedCStri(columnValue)););
3997     return columnValue;
3998   } /* sqlColumnStri */
3999 
4000 
4001 
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)4002 static void sqlColumnTime (sqlStmtType sqlStatement, intType column,
4003     intType *year, intType *month, intType *day, intType *hour,
4004     intType *minute, intType *second, intType *micro_second,
4005     intType *time_zone, boolType *is_dst)
4006 
4007   {
4008     preparedStmtType preparedStmt;
4009     resultDataType columnData;
4010     unsigned char *sqltDat;
4011     sb2 ociYear;
4012     ub1 ociMonth;
4013     ub1 ociDay;
4014     ub1 ociHour;
4015     ub1 ociMinute;
4016     ub1 ociSecond;
4017     ub4 ociFsec;
4018     sb1 tzHour;
4019     sb1 tzMinute;
4020     errInfoType err_info = OKAY_NO_ERROR;
4021 
4022   /* sqlColumnTime */
4023     logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", *)\n",
4024                        (memSizeType) sqlStatement, column););
4025     preparedStmt = (preparedStmtType) sqlStatement;
4026     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4027                  (uintType) column > preparedStmt->result_array_size)) {
4028       logError(printf("sqlColumnTime: Fetch okay: %d, column: " FMT_D
4029                       ", max column: " FMT_U_MEM ".\n",
4030                       preparedStmt->fetchOkay, column,
4031                       preparedStmt->result_array_size););
4032       raise_error(RANGE_ERROR);
4033     } else {
4034       columnData = &preparedStmt->result_array[column - 1];
4035       if (columnData->indicator == -1) {
4036         /* printf("Column is NULL -> Use default value: 0-01-01 00:00:00\n"); */
4037         *year         = 0;
4038         *month        = 1;
4039         *day          = 1;
4040         *hour         = 0;
4041         *minute       = 0;
4042         *second       = 0;
4043         *micro_second = 0;
4044         *time_zone    = 0;
4045         *is_dst       = 0;
4046       } else if (columnData->indicator != 0) {
4047         dbInconsistent("sqlColumnTime", "OCIDefineByPos");
4048         logError(printf("sqlColumnTime: Column " FMT_D " has indicator: %d\n",
4049                         column, columnData->indicator););
4050         err_info = DATABASE_ERROR;
4051       } else {
4052         /* printf("buffer_type: %s\n",
4053            nameOfBufferType(columnData->buffer_type)); */
4054         switch (columnData->buffer_type) {
4055           case SQLT_DAT: /* DATE */
4056             sqltDat = (unsigned char *) columnData->buffer;
4057             ociYear = (sb2) ((sqltDat[0] - 101) * 100 + sqltDat[1]);
4058             if (ociYear <= -1) {
4059               /* In the proleptic Gregorian calendar the year preceding 1 is 0. */
4060               ociYear++;
4061             } /* if */
4062             *year   = ociYear;
4063             *month  = sqltDat[2];
4064             *day    = sqltDat[3];
4065             *hour   = sqltDat[4] - 1;
4066             *minute = sqltDat[5] - 1;
4067             *second = sqltDat[6] - 1;
4068             *micro_second = 0;
4069             timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
4070                           time_zone, is_dst);
4071             break;
4072           case SQLT_DATE:
4073           case SQLT_TIMESTAMP:
4074           case SQLT_TIMESTAMP_TZ:
4075           case SQLT_TIMESTAMP_LTZ:
4076             OCIDateTimeGetDate(preparedStmt->oci_environment,
4077                                preparedStmt->oci_error,
4078                                (OCIDateTime *) columnData->descriptor,
4079                                &ociYear,
4080                                &ociMonth,
4081                                &ociDay);
4082             if (ociYear <= -1) {
4083               /* In the proleptic Gregorian calendar the year preceding 1 is 0. */
4084               ociYear++;
4085             } /* if */
4086             *year  = ociYear;
4087             *month = ociMonth;
4088             *day   = ociDay;
4089             OCIDateTimeGetTime(preparedStmt->oci_environment,
4090                                preparedStmt->oci_error,
4091                                (OCIDateTime *) columnData->descriptor,
4092                                &ociHour,
4093                                &ociMinute,
4094                                &ociSecond,
4095                                &ociFsec);
4096             *hour   = ociHour;
4097             *minute = ociMinute;
4098             *second = ociSecond;
4099             *micro_second = ociFsec / 1000;
4100             if (columnData->buffer_type == SQLT_TIMESTAMP_TZ || columnData->buffer_type == SQLT_DATE) {
4101               OCIDateTimeGetTimeZoneOffset(preparedStmt->oci_environment,
4102                                            preparedStmt->oci_error,
4103                                            (OCIDateTime *) columnData->descriptor,
4104                                            &tzHour, &tzMinute);
4105               /* printf(F_D16(02) ":" F_D16(02) "\n", tzHour, tzMinute); */
4106               *time_zone = tzHour * 60 + tzMinute;
4107               *is_dst = FALSE;
4108             } else {
4109               timSetLocalTZ(*year, *month, *day, *hour, *minute, *second,
4110                             time_zone, is_dst);
4111             } /* if */
4112             break;
4113           default:
4114             logError(printf("sqlColumnTime: Column " FMT_D " has the unknown type %s.\n",
4115                             column, nameOfBufferType(columnData->buffer_type)););
4116             err_info = RANGE_ERROR;
4117             break;
4118         } /* switch */
4119         if (unlikely(err_info != OKAY_NO_ERROR)) {
4120           raise_error(err_info);
4121         } /* if */
4122       } /* if */
4123     } /* if */
4124     logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", "
4125                                         F_D(04) "-" F_D(02) "-" F_D(02) " "
4126                                         F_D(02) ":" F_D(02) ":" F_D(02) "."
4127                                         F_D(06) ", " FMT_D ", %d) -->\n",
4128                        (memSizeType) sqlStatement, column,
4129                        *year, *month, *day, *hour, *minute, *second,
4130                        *micro_second, *time_zone, *is_dst););
4131   } /* sqlColumnTime */
4132 
4133 
4134 
sqlCommit(databaseType database)4135 static void sqlCommit (databaseType database)
4136 
4137   {
4138     dbType db;
4139 
4140   /* sqlCommit */
4141     logFunction(printf("sqlCommit(" FMT_U_MEM ")\n",
4142                        (memSizeType) database););
4143     db = (dbType) database;
4144     OCITransCommit(db->oci_service_context,
4145                    db->oci_error,
4146                    OCI_DEFAULT);
4147     logFunction(printf("sqlCommit -->\n"););
4148   } /* sqlCommit */
4149 
4150 
4151 
sqlExecute(sqlStmtType sqlStatement)4152 static void sqlExecute (sqlStmtType sqlStatement)
4153 
4154   {
4155     preparedStmtType preparedStmt;
4156     ub4 executeMode;
4157 
4158   /* sqlExecute */
4159     logFunction(printf("sqlExecute(" FMT_U_MEM ")\n",
4160                        (memSizeType) sqlStatement););
4161     preparedStmt = (preparedStmtType) sqlStatement;
4162     if (unlikely(!allParametersBound(preparedStmt))) {
4163       dbLibError("sqlExecute", "SQLExecute",
4164                  "Unbound statement parameter(s).\n");
4165       raise_error(DATABASE_ERROR);
4166     } else {
4167       /* printf("ppStmt: " FMT_X_MEM "\n", (memSizeType) preparedStmt->ppStmt); */
4168       preparedStmt->fetchOkay = FALSE;
4169       /* showBindVars(preparedStmt); */
4170       /* showResultVars(preparedStmt); */
4171       executeMode = preparedStmt->db->autoCommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT;
4172       if (unlikely(OCIStmtExecute(preparedStmt->oci_service_context,
4173                                   preparedStmt->ppStmt,
4174                                   preparedStmt->oci_error,
4175                                   preparedStmt->statementType != OCI_STMT_SELECT, /* iters */
4176                                   0, NULL, NULL,
4177                                   executeMode) != OCI_SUCCESS)) {
4178         setDbErrorMsg("sqlExecute", "OCIStmtExecute",
4179                       preparedStmt->oci_error);
4180         logError(printf("sqlExecute: OCIStmtExecute:\n%s\n",
4181                         dbError.message););
4182         preparedStmt->executeSuccessful = FALSE;
4183         raise_error(DATABASE_ERROR);
4184       } else {
4185         preparedStmt->executeSuccessful = TRUE;
4186         preparedStmt->fetchFinished = FALSE;
4187       } /* if */
4188     } /* if */
4189     logFunction(printf("sqlExecute -->\n"););
4190   } /* sqlExecute */
4191 
4192 
4193 
sqlFetch(sqlStmtType sqlStatement)4194 static boolType sqlFetch (sqlStmtType sqlStatement)
4195 
4196   {
4197     preparedStmtType preparedStmt;
4198     int fetch_result;
4199 
4200   /* sqlFetch */
4201     logFunction(printf("sqlFetch(" FMT_U_MEM ")\n",
4202                        (memSizeType) sqlStatement););
4203     preparedStmt = (preparedStmtType) sqlStatement;
4204     if (unlikely(!preparedStmt->executeSuccessful)) {
4205       dbLibError("sqlFetch", "OCIStmtExecute",
4206                  "Execute was not successful.\n");
4207       logError(printf("sqlFetch: Execute was not successful.\n"););
4208       preparedStmt->fetchOkay = FALSE;
4209       raise_error(DATABASE_ERROR);
4210     } else if (preparedStmt->result_array_size == 0) {
4211       preparedStmt->fetchOkay = FALSE;
4212     } else if (!preparedStmt->fetchFinished) {
4213       /* printf("ppStmt: " FMT_X_MEM "\n", (memSizeType) preparedStmt->ppStmt); */
4214       fetch_result = OCIStmtFetch2(preparedStmt->ppStmt,
4215                                    preparedStmt->oci_error,
4216                                    1, /* Number of rows */
4217                                    OCI_FETCH_NEXT,
4218                                    0, /* Fetch offset */
4219                                    OCI_DEFAULT);
4220       if (fetch_result == OCI_SUCCESS) {
4221         /* printf("fetch success\n");
4222         showResultVars(preparedStmt); */
4223         preparedStmt->fetchOkay = TRUE;
4224       /* } else if (fetch_result == -1) {
4225         printf("fetch_result: %d\n", fetch_result);
4226         printError(preparedStmt->oci_error);
4227         showResultVars(preparedStmt);
4228         preparedStmt->fetchOkay = TRUE; */
4229       } else if (fetch_result == OCI_NO_DATA) {
4230         preparedStmt->fetchOkay = FALSE;
4231         preparedStmt->fetchFinished = TRUE;
4232       } else {
4233         setDbErrorMsg("sqlFetch", "OCIStmtFetch2",
4234                       preparedStmt->oci_error);
4235         logError(printf("sqlFetch: OCIStmtFetch2 fetch_result: %d:\n%s\n",
4236                         fetch_result, dbError.message););
4237         preparedStmt->fetchOkay = FALSE;
4238         preparedStmt->fetchFinished = TRUE;
4239         raise_error(DATABASE_ERROR);
4240       } /* if */
4241     } /* if */
4242     logFunction(printf("sqlFetch --> %d\n", preparedStmt->fetchOkay););
4243     return preparedStmt->fetchOkay;
4244   } /* sqlFetch */
4245 
4246 
4247 
sqlGetAutoCommit(databaseType database)4248 static boolType sqlGetAutoCommit (databaseType database)
4249 
4250   {
4251     dbType db;
4252     boolType autoCommit;
4253 
4254   /* sqlGetAutoCommit */
4255     logFunction(printf("sqlGetAutoCommit(" FMT_U_MEM ")\n",
4256                        (memSizeType) database););
4257     db = (dbType) database;
4258     autoCommit = db->autoCommit;
4259     logFunction(printf("sqlGetAutoCommit --> %d\n", autoCommit););
4260     return autoCommit;
4261   } /* sqlGetAutoCommit */
4262 
4263 
4264 
sqlIsNull(sqlStmtType sqlStatement,intType column)4265 static boolType sqlIsNull (sqlStmtType sqlStatement, intType column)
4266 
4267   {
4268     preparedStmtType preparedStmt;
4269     boolType isNull;
4270 
4271   /* sqlIsNull */
4272     logFunction(printf("sqlIsNull(" FMT_U_MEM ", " FMT_D ")\n",
4273                        (memSizeType) sqlStatement, column););
4274     preparedStmt = (preparedStmtType) sqlStatement;
4275     if (unlikely(!preparedStmt->fetchOkay || column < 1 ||
4276                  (uintType) column > preparedStmt->result_array_size)) {
4277       logError(printf("sqlIsNull: Fetch okay: %d, column: " FMT_D
4278                       ", max column: " FMT_U_MEM ".\n",
4279                       preparedStmt->fetchOkay, column,
4280                       preparedStmt->result_array_size););
4281       raise_error(RANGE_ERROR);
4282       isNull = FALSE;
4283     } else {
4284       isNull = preparedStmt->result_array[column - 1].indicator == -1;
4285     } /* if */
4286     logFunction(printf("sqlIsNull --> %s\n", isNull ? "TRUE" : "FALSE"););
4287     return isNull;
4288   } /* sqlIsNull */
4289 
4290 
4291 
sqlPrepare(databaseType database,const const_striType sqlStatementStri)4292 static sqlStmtType sqlPrepare (databaseType database,
4293     const const_striType sqlStatementStri)
4294 
4295   {
4296     dbType db;
4297     striType statementStri;
4298     memSizeType numBindParameters;
4299     cstriType query;
4300     memSizeType queryLength;
4301     errInfoType err_info = OKAY_NO_ERROR;
4302     preparedStmtType preparedStmt;
4303 
4304   /* sqlPrepare */
4305     logFunction(printf("sqlPrepare(" FMT_U_MEM ", \"%s\")\n",
4306                        (memSizeType) database,
4307                        striAsUnquotedCStri(sqlStatementStri)););
4308     db = (dbType) database;
4309     statementStri = processStatementStri(sqlStatementStri, &numBindParameters, &err_info);
4310     if (statementStri == NULL) {
4311       preparedStmt = NULL;
4312     } else {
4313       query = stri_to_cstri8_buf(statementStri, &queryLength);
4314       if (unlikely(query == NULL)) {
4315         err_info = MEMORY_ERROR;
4316         preparedStmt = NULL;
4317       } else {
4318         /* printf("query: \"%s\"\n", query); */
4319         if (queryLength > UB4MAXVAL) {
4320           /* It is not possible to cast queryLength to ub4. */
4321           logError(printf("sqlPrepare: Statement string too long (length = " FMT_U_MEM ")\n",
4322                           queryLength););
4323           err_info = RANGE_ERROR;
4324           preparedStmt = NULL;
4325         } else if (!ALLOC_RECORD2(preparedStmt, preparedStmtRecord,
4326                                   count.prepared_stmt, count.prepared_stmt_bytes)) {
4327           err_info = MEMORY_ERROR;
4328         } else {
4329           /* printf("sqlPrepare: query: %s\n", query); */
4330           memset(preparedStmt, 0, sizeof(preparedStmtRecord));
4331           if (OCIHandleAlloc(db->oci_environment, (void **) &preparedStmt->ppStmt,
4332                              OCI_HTYPE_STMT, 0, NULL) != OCI_SUCCESS ||
4333               OCIStmtPrepare(preparedStmt->ppStmt, db->oci_error,
4334                              (OraText *) query, (ub4) queryLength,
4335                              OCI_NTV_SYNTAX, OCI_DEFAULT) != OCI_SUCCESS) {
4336             setDbErrorMsg("sqlPrepare", "OCIStmtPrepare", db->oci_error);
4337             logError(printf("sqlPrepare: OCIStmtPrepare:\n%s\n",
4338                             dbError.message););
4339             FREE_RECORD2(preparedStmt, preparedStmtRecord,
4340                          count.prepared_stmt, count.prepared_stmt_bytes);
4341             err_info = DATABASE_ERROR;
4342             preparedStmt = NULL;
4343           } else {
4344             preparedStmt->usage_count = 1;
4345             preparedStmt->sqlFunc = db->sqlFunc;
4346             preparedStmt->oci_environment = db->oci_environment;
4347             preparedStmt->oci_error = db->oci_error;
4348             preparedStmt->oci_service_context = db->oci_service_context;
4349             preparedStmt->charSetId = db->charSetId;
4350             preparedStmt->executeSuccessful = FALSE;
4351             preparedStmt->fetchOkay = FALSE;
4352             preparedStmt->fetchFinished = TRUE;
4353             preparedStmt->db = db;
4354             db->usage_count++;
4355             err_info = setupParameters(preparedStmt, numBindParameters);
4356             if (unlikely(err_info != OKAY_NO_ERROR)) {
4357               preparedStmt->result_array = NULL;
4358             } else {
4359               err_info = setupResult(preparedStmt);
4360             } /* if */
4361             if (unlikely(err_info != OKAY_NO_ERROR)) {
4362               freePreparedStmt((sqlStmtType) preparedStmt);
4363               preparedStmt = NULL;
4364             } /* if */
4365           } /* if */
4366         } /* if */
4367         free_cstri8(query, statementStri);
4368       } /* if */
4369       FREE_STRI(statementStri, sqlStatementStri->size * MAX_BIND_VAR_SIZE);
4370     } /* if */
4371     if (unlikely(err_info != OKAY_NO_ERROR)) {
4372       raise_error(err_info);
4373     } /* if */
4374     logFunction(printf("sqlPrepare --> " FMT_U_MEM "\n",
4375                        (memSizeType) preparedStmt););
4376     return (sqlStmtType) preparedStmt;
4377   } /* sqlPrepare */
4378 
4379 
4380 
sqlRollback(databaseType database)4381 static void sqlRollback (databaseType database)
4382 
4383   {
4384     dbType db;
4385 
4386   /* sqlRollback */
4387     logFunction(printf("sqlRollback(" FMT_U_MEM ")\n",
4388                        (memSizeType) database););
4389     db = (dbType) database;
4390     OCITransRollback(db->oci_service_context,
4391                    db->oci_error,
4392                    OCI_DEFAULT);
4393     logFunction(printf("sqlRollback -->\n"););
4394   } /* sqlRollback */
4395 
4396 
4397 
sqlSetAutoCommit(databaseType database,boolType autoCommit)4398 static void sqlSetAutoCommit (databaseType database, boolType autoCommit)
4399 
4400   {
4401     dbType db;
4402 
4403   /* sqlSetAutoCommit */
4404     logFunction(printf("sqlSetAutoCommit(" FMT_U_MEM ", %d)\n",
4405                        (memSizeType) database, autoCommit););
4406     db = (dbType) database;
4407     db->autoCommit = autoCommit;
4408     logFunction(printf("sqlSetAutoCommit -->\n"););
4409   } /* sqlSetAutoCommit */
4410 
4411 
4412 
sqlStmtColumnCount(sqlStmtType sqlStatement)4413 static intType sqlStmtColumnCount (sqlStmtType sqlStatement)
4414 
4415   {
4416     preparedStmtType preparedStmt;
4417     intType columnCount;
4418 
4419   /* sqlStmtColumnCount */
4420     logFunction(printf("sqlStmtColumnCount(" FMT_U_MEM ")\n",
4421                        (memSizeType) sqlStatement););
4422     preparedStmt = (preparedStmtType) sqlStatement;
4423     if (unlikely(preparedStmt->result_array_size > INTTYPE_MAX)) {
4424       logError(printf("sqlStmtColumnCount: "
4425                       "result_array_size (=" FMT_U_MEM ") > INTTYPE_MAX\n",
4426                       preparedStmt->result_array_size););
4427       raise_error(RANGE_ERROR);
4428       columnCount = 0;
4429     } else {
4430       columnCount = (intType) preparedStmt->result_array_size;
4431     } /* if */
4432     logFunction(printf("sqlStmtColumnCount --> " FMT_D "\n", columnCount););
4433     return columnCount;
4434   } /* sqlStmtColumnCount */
4435 
4436 
4437 
sqlStmtColumnName(sqlStmtType sqlStatement,intType column)4438 static striType sqlStmtColumnName (sqlStmtType sqlStatement, intType column)
4439 
4440   {
4441     preparedStmtType preparedStmt;
4442     cstriType col_name;
4443     ub4 col_name_len = 0;
4444     errInfoType err_info = OKAY_NO_ERROR;
4445     striType name;
4446 
4447   /* sqlStmtColumnName */
4448     logFunction(printf("sqlStmtColumnName(" FMT_U_MEM ", " FMT_D ")\n",
4449                        (memSizeType) sqlStatement, column););
4450     preparedStmt = (preparedStmtType) sqlStatement;
4451     if (unlikely(column < 1 ||
4452                  (uintType) column > preparedStmt->result_array_size)) {
4453       logError(printf("sqlStmtColumnName: column: " FMT_D
4454                       ", max column: " FMT_U_MEM ".\n",
4455                       column, preparedStmt->result_array_size););
4456       raise_error(RANGE_ERROR);
4457       name = NULL;
4458     } else if (unlikely(OCIAttrGet(preparedStmt->result_array[column - 1].column_handle,
4459                                    OCI_DTYPE_PARAM,
4460                                    &col_name,
4461                                    &col_name_len,
4462                                    OCI_ATTR_NAME,
4463                                    preparedStmt->oci_error) != OCI_SUCCESS)) {
4464       setDbErrorMsg("sqlStmtColumnName", "OCIAttrGet",
4465                     preparedStmt->oci_error);
4466       logError(printf("sqlStmtColumnName: OCIAttrGet OCI_ATTR_NAME:\n%s\n",
4467                       dbError.message););
4468       raise_error(DATABASE_ERROR);
4469       name = NULL;
4470     } else {
4471       name = cstri8_buf_to_stri(col_name, (memSizeType) col_name_len, &err_info);
4472       if (unlikely(name == NULL)) {
4473         raise_error(err_info);
4474       } /* if */
4475     } /* if */
4476     logFunction(printf("sqlStmtColumnName --> \"%s\"\n",
4477                        striAsUnquotedCStri(name)););
4478     return name;
4479   } /* sqlStmtColumnName */
4480 
4481 
4482 
4483 #if 0
4484 static rtlTypeType sqlStmtColumnType (sqlStmtType sqlStatement, intType column)
4485 
4486   {
4487     preparedStmtType preparedStmt;
4488     resultDataType columnData;
4489     sb2 precision; /* This is for an implicit describe with OCIStmtExecute() */
4490     sb1 scale;
4491     rtlTypeType columnType;
4492 
4493   /* sqlStmtColumnType */
4494     logFunction(printf("sqlStmtColumnType(" FMT_U_MEM ", " FMT_D ")\n",
4495                        (memSizeType) sqlStatement, column); */
4496     preparedStmt = (preparedStmtType) sqlStatement;
4497     if (unlikely(column < 1 ||
4498                  (uintType) column > preparedStmt->result_array_size)) {
4499       logError(printf("sqlStmtColumnType: column: " FMT_D
4500                       ", max column: " FMT_U_MEM ".\n",
4501                       column, preparedStmt->result_array_size););
4502       raise_error(RANGE_ERROR);
4503       columnType = SYS_VOID_TYPE;
4504     } else {
4505       columnData = &preparedStmt->result_array[column - 1];
4506       switch (columnData->buffer_type) {
4507         case SQLT_CHR: /* VARCHAR2 */
4508         case SQLT_VCS: /* VARCHAR */
4509         case SQLT_LNG: /* LONG */
4510         case SQLT_LVC: /* LONG VARCHAR */
4511         case SQLT_AFC: /* CHAR */
4512         case SQLT_STR: /* NULL-terminated STRING */
4513         case SQLT_AVC: /* CHARZ */
4514         case SQLT_VST: /* OCI STRING type */
4515         case SQLT_CLOB: /* Character LOB  */
4516           columnType = SYS_STRI_TYPE;
4517           break;
4518         case SQLT_BIN: /* RAW */
4519         case SQLT_VBI: /* VARRAW */
4520         case SQLT_LBI: /* LONG RAW */
4521         case SQLT_LVB: /* LONG VARRAW */
4522         case SQLT_BLOB: /* Binary LOB */
4523         case SQLT_FILE: /* Binary FILE */
4524           columnType = SYS_BSTRI_TYPE;
4525           break;
4526         case SQLT_RDD: /* ROWID */
4527           columnType = SYS_STRI_TYPE;
4528           break;
4529         case SQLT_NUM:
4530           if (unlikely(OCIAttrGet(columnData->column_handle,
4531                                   OCI_DTYPE_PARAM,
4532                                   (dvoid *) &precision, NULL, OCI_ATTR_PRECISION,
4533                                   preparedStmt->oci_error) != OCI_SUCCESS)) {
4534             setDbErrorMsg("sqlStmtColumnType", "OCIAttrGet",
4535                           preparedStmt->oci_error);
4536             logError(printf("sqlStmtColumnType: OCIAttrGet OCI_ATTR_PRECISION:\n%s\n",
4537                             dbError.message););
4538             raise_error(DATABASE_ERROR);
4539           } else if (unlikely(OCIAttrGet(columnData->column_handle,
4540                                          OCI_DTYPE_PARAM,
4541                                          (dvoid *) &scale, NULL, OCI_ATTR_SCALE,
4542                                          preparedStmt->oci_error) != OCI_SUCCESS)) {
4543             setDbErrorMsg("sqlStmtColumnType", "OCIAttrGet",
4544                           preparedStmt->oci_error);
4545             logError(printf("sqlStmtColumnType: OCIAttrGet OCI_ATTR_SCALE:\n%s\n",
4546                             dbError.message););
4547             raise_error(DATABASE_ERROR);
4548           } else {
4549             printf("precision: %u\n", precision);
4550             printf("scale: %u\n", scale);
4551             if (scale <= 0) {
4552               if (precision - scale <= DECIMAL_DIGITS_IN_INTTYPE) {
4553                 columnType = SYS_INT_TYPE;
4554               } else {
4555                 columnType = SYS_BIGINT_TYPE;
4556               } /* if */
4557             } else {
4558               columnType = SYS_BIGRAT_TYPE;
4559             } /* if */
4560           } /* if */
4561           break;
4562         default:
4563           logError(printf("sqlStmtColumnType: Column " FMT_D " has the unknown type %s.\n",
4564                           column, nameOfBufferType(
4565                           columnData->buffer_type)););
4566           raise_error(RANGE_ERROR);
4567           columnType = SYS_VOID_TYPE;
4568           break;
4569       } /* switch */
4570     } /* if */
4571     return columnType;
4572   } /* sqlStmtColumnType */
4573 #endif
4574 
4575 
4576 
setupFuncTable(void)4577 static boolType setupFuncTable (void)
4578 
4579   { /* setupFuncTable */
4580     if (sqlFunc == NULL) {
4581       if (ALLOC_RECORD(sqlFunc, sqlFuncRecord, count.sql_func)) {
4582         memset(sqlFunc, 0, sizeof(sqlFuncRecord));
4583         sqlFunc->freeDatabase       = &freeDatabase;
4584         sqlFunc->freePreparedStmt   = &freePreparedStmt;
4585         sqlFunc->sqlBindBigInt      = &sqlBindBigInt;
4586         sqlFunc->sqlBindBigRat      = &sqlBindBigRat;
4587         sqlFunc->sqlBindBool        = &sqlBindBool;
4588         sqlFunc->sqlBindBStri       = &sqlBindBStri;
4589         sqlFunc->sqlBindDuration    = &sqlBindDuration;
4590         sqlFunc->sqlBindFloat       = &sqlBindFloat;
4591         sqlFunc->sqlBindInt         = &sqlBindInt;
4592         sqlFunc->sqlBindNull        = &sqlBindNull;
4593         sqlFunc->sqlBindStri        = &sqlBindStri;
4594         sqlFunc->sqlBindTime        = &sqlBindTime;
4595         sqlFunc->sqlClose           = &sqlClose;
4596         sqlFunc->sqlColumnBigInt    = &sqlColumnBigInt;
4597         sqlFunc->sqlColumnBigRat    = &sqlColumnBigRat;
4598         sqlFunc->sqlColumnBool      = &sqlColumnBool;
4599         sqlFunc->sqlColumnBStri     = &sqlColumnBStri;
4600         sqlFunc->sqlColumnDuration  = &sqlColumnDuration;
4601         sqlFunc->sqlColumnFloat     = &sqlColumnFloat;
4602         sqlFunc->sqlColumnInt       = &sqlColumnInt;
4603         sqlFunc->sqlColumnStri      = &sqlColumnStri;
4604         sqlFunc->sqlColumnTime      = &sqlColumnTime;
4605         sqlFunc->sqlCommit          = &sqlCommit;
4606         sqlFunc->sqlExecute         = &sqlExecute;
4607         sqlFunc->sqlFetch           = &sqlFetch;
4608         sqlFunc->sqlGetAutoCommit   = &sqlGetAutoCommit;
4609         sqlFunc->sqlIsNull          = &sqlIsNull;
4610         sqlFunc->sqlPrepare         = &sqlPrepare;
4611         sqlFunc->sqlRollback        = &sqlRollback;
4612         sqlFunc->sqlSetAutoCommit   = &sqlSetAutoCommit;
4613         sqlFunc->sqlStmtColumnCount = &sqlStmtColumnCount;
4614         sqlFunc->sqlStmtColumnName  = &sqlStmtColumnName;
4615       } /* if */
4616     } /* if */
4617     return sqlFunc != NULL;
4618   } /* setupFuncTable */
4619 
4620 
4621 
setupConnectData(const_cstriType host8,intType port,const_cstriType dbName8,connectDataType connectData)4622 static boolType setupConnectData (const_cstriType host8, intType port, const_cstriType dbName8, connectDataType connectData)
4623 
4624   {
4625     boolType possibleTnsName;
4626     memSizeType portNameLength;
4627     char portName[INTTYPE_DECIMAL_SIZE + NULL_TERMINATION_LEN];
4628     memSizeType host8Length;
4629     memSizeType dbName8Length;
4630     boolType okay = FALSE;
4631 
4632   /* setupConnectData */
4633     logFunction(printf("setupConnectData(\"%s\", " FMT_D ", \"%s\", *)\n",
4634                        host8, port, dbName8););
4635     possibleTnsName = host8[0] == '\0' && port == 0;
4636     if (host8[0] == '\0') {
4637       host8 = "localhost";
4638     } /* if */
4639     if (port == 0) {
4640       port = DEFAULT_PORT;
4641     } /* if */
4642     portNameLength = (memSizeType) sprintf(portName, FMT_D, port);
4643     host8Length = strlen(host8);
4644     dbName8Length = strlen(dbName8);
4645     if (likely(host8Length <= MAX_CSTRI_LEN / 4 && dbName8Length <= MAX_CSTRI_LEN / 4)) {
4646       /* The computation of the connect string lengths is safe. */
4647       /* printf("host8: \"%s\"\n", host8);
4648          printf("port: \"%s\"\n", portName);
4649          printf("dbName8: \"%s\"\n", dbName8); */
4650       memset(connectData, 0, sizeof(connectDataRecord));
4651       if (possibleTnsName &&
4652           ALLOC_CSTRI(connectData->tnsName, dbName8Length)) {
4653         connectData->tnsNameLength = dbName8Length;
4654         memcpy(connectData->tnsName, dbName8, dbName8Length + NULL_TERMINATION_LEN);
4655       } /* if */
4656       if (likely(!possibleTnsName || connectData->tnsName != NULL)) {
4657         connectData->connectStringServiceLength = STRLEN(CONNECT_STRING_SERVICE_TEMPLATE) - 3 * 2 +
4658             host8Length + portNameLength + dbName8Length;
4659         connectData->connectStringSidLength = STRLEN(CONNECT_STRING_SID_TEMPLATE) - 3 * 2 +
4660             host8Length + portNameLength + dbName8Length;
4661         if (unlikely(!ALLOC_CSTRI(connectData->connectStringService,
4662                                   connectData->connectStringServiceLength) ||
4663                      !ALLOC_CSTRI(connectData->connectStringSid,
4664                                   connectData->connectStringSidLength))) {
4665           UNALLOC_CSTRI(connectData->tnsName, connectData->tnsNameLength);
4666           UNALLOC_CSTRI(connectData->connectStringService, connectData->connectStringServiceLength);
4667           UNALLOC_CSTRI(connectData->connectStringSid, connectData->connectStringSidLength);
4668         } else {
4669           sprintf(connectData->connectStringService, CONNECT_STRING_SERVICE_TEMPLATE,
4670                   host8, portName, dbName8);
4671           sprintf(connectData->connectStringSid, CONNECT_STRING_SID_TEMPLATE,
4672                   host8, portName, dbName8);
4673           /* printf("connectStringService: %s\n", connectData->connectStringService);
4674              printf("connectStringServiceLength: " FMT_U_MEM "\n",
4675                     connectData->connectStringServiceLength); */
4676           /* printf("connectStringSid: %s\n", connectData->connectStringSid);
4677              printf("connectStringSidLength: " FMT_U_MEM "\n",
4678                     connectData->connectStringSidLength); */
4679           okay = TRUE;
4680         } /* if */
4681       } /* if */
4682     } /* if */
4683     logFunction(printf("setupConnectData --> \"%d\"\n", okay););
4684     return okay;
4685   } /* setupConnectData */
4686 
4687 
4688 
sqlOpenOci(const const_striType host,intType port,const const_striType dbName,const const_striType user,const const_striType password)4689 databaseType sqlOpenOci (const const_striType host, intType port,
4690     const const_striType dbName, const const_striType user,
4691     const const_striType password)
4692 
4693   {
4694     const_cstriType host8;
4695     const_cstriType dbName8;
4696     connectDataRecord connectData;
4697     cstriType user8;
4698     memSizeType user8Length;
4699     cstriType password8;
4700     memSizeType password8Length;
4701     dbRecord db;
4702     errInfoType err_info = OKAY_NO_ERROR;
4703     dbType database;
4704 
4705   /* sqlOpenOci */
4706     logFunction(printf("sqlOpenOci(\"%s\", ",
4707                        striAsUnquotedCStri(host));
4708                 printf(FMT_D ", \"%s\", ",
4709                        port, striAsUnquotedCStri(dbName));
4710                 printf("\"%s\", ", striAsUnquotedCStri(user));
4711                 printf("\"%s\")\n", striAsUnquotedCStri(password)););
4712     if (!findDll()) {
4713       logError(printf("sqlOpenOci: findDll() failed\n"););
4714       err_info = DATABASE_ERROR;
4715       database = NULL;
4716     } else if (unlikely((host8 = stri_to_cstri8(host, &err_info)) == NULL)) {
4717       database = NULL;
4718     } else {
4719       if (unlikely((dbName8 = stri_to_cstri8(dbName, &err_info)) == NULL)) {
4720         database = NULL;
4721       } else {
4722         if (unlikely(!setupConnectData(host8, port, dbName8, &connectData))) {
4723           err_info = MEMORY_ERROR;
4724           database = NULL;
4725         } else {
4726           user8 = stri_to_cstri8_buf(user, &user8Length);
4727           if (unlikely(user8 == NULL)) {
4728             err_info = MEMORY_ERROR;
4729             database = NULL;
4730           } else {
4731             password8 = stri_to_cstri8_buf(password, &password8Length);
4732             if (unlikely(password8 == NULL)) {
4733               err_info = MEMORY_ERROR;
4734               database = NULL;
4735             } else {
4736               memset(&db, 0, sizeof(dbRecord));
4737               /* printf("dbName:         %s\n", connectData.tnsName);
4738                  printf("connectString1: %s\n", connectData.connectStringService);
4739                  printf("connectString2: %s\n", connectData.connectStringSid);
4740                  printf("user:           %s\n", user8);
4741                  printf("password:       %s\n", password8); */
4742               if (connectData.tnsNameLength              > SB4MAXVAL ||
4743                   connectData.connectStringServiceLength > SB4MAXVAL ||
4744                   connectData.connectStringSidLength     > SB4MAXVAL ||
4745                   user8Length         > UB4MAXVAL ||
4746                   password8Length     > UB4MAXVAL) {
4747                 /* It is not possible to cast the lengths to sb4 and ub4. */
4748                 err_info = MEMORY_ERROR;
4749                 database = NULL;
4750               } else if (OCIEnvCreate(&db.oci_environment, OCI_DEFAULT,
4751                                       NULL, NULL, NULL, NULL, 0, NULL) != OCI_SUCCESS) {
4752                 dbLibError("sqlOpenOci", "OCIEnvCreate",
4753                            "OCIEnvCreate failed.\n");
4754                 logError(printf("sqlOpenOci: OCIEnvCreate failed\n"););
4755                 sqlClose((databaseType) &db);
4756                 err_info = DATABASE_ERROR;
4757                 database = NULL;
4758               } else if ((db.charSetId = OCINlsCharSetNameToId(db.oci_environment, (oratext *) "AL32UTF8")) == 0) {
4759                 dbLibError("sqlOpenOci", "OCINlsCharSetNameToId",
4760                            "OCINlsCharSetNameToId(*, \"AL32UTF8\") failed.\n");
4761                 logError(printf("sqlOpenOci: OCINlsCharSetNameToId(*, \"AL32UTF8\") failed\n"););
4762                 sqlClose((databaseType) &db);
4763                 err_info = DATABASE_ERROR;
4764                 database = NULL;
4765               } else if (OCIHandleFree(db.oci_environment, OCI_HTYPE_ENV) != OCI_SUCCESS) {
4766                 dbLibError("sqlOpenOci", "OCIHandleFree",
4767                            "OCIHandleFree failed.\n");
4768                 logError(printf("sqlOpenOci: OCIHandleFree failed\n"););
4769                 sqlClose((databaseType) &db);
4770                 err_info = DATABASE_ERROR;
4771                 database = NULL;
4772               } else if (OCIEnvNlsCreate(&db.oci_environment, OCI_OBJECT, /* OCI_DEFAULT, */
4773                                          NULL, NULL, NULL, NULL, 0, NULL,
4774                                          db.charSetId, db.charSetId) != OCI_SUCCESS) {
4775                 dbLibError("sqlOpenOci", "OCIEnvNlsCreate",
4776                            "OCIEnvNlsCreate failed.\n");
4777                 logError(printf("sqlOpenOci: OCIEnvNlsCreate failed\n"););
4778                 err_info = DATABASE_ERROR;
4779                 sqlClose((databaseType) &db);
4780                 database = NULL;
4781               } else if (OCIHandleAlloc(db.oci_environment,
4782                                         (dvoid **) &db.oci_server,
4783                                         OCI_HTYPE_SERVER, 0, NULL) != OCI_SUCCESS ||
4784                          OCIHandleAlloc(db.oci_environment,
4785                                         (void **) &db.oci_error,
4786                                         OCI_HTYPE_ERROR, 0, NULL) != OCI_SUCCESS ||
4787                          OCIHandleAlloc(db.oci_environment,
4788                                         (void **) &db.oci_service_context,
4789                                         OCI_HTYPE_SVCCTX, 0, NULL) != OCI_SUCCESS ||
4790                          OCIHandleAlloc(db.oci_environment,
4791                                         (dvoid **) &db.oci_session,
4792                                         OCI_HTYPE_SESSION, 0, NULL) != OCI_SUCCESS) {
4793                 dbLibError("sqlOpenOci", "OCIHandleAlloc",
4794                            "OCIHandleAlloc failed.\n");
4795                 logError(printf("sqlOpenOci: OCIHandleAlloc failed\n"););
4796                 err_info = DATABASE_ERROR;
4797                 sqlClose((databaseType) &db);
4798                 database = NULL;
4799               } else if ((connectData.tnsName == NULL ||
4800                           /* Possible TNS name: No host and no port has been specified. */
4801                           OCIServerAttach(db.oci_server, db.oci_error,
4802                                           (OraText *) connectData.tnsName,
4803                                           (sb4) connectData.tnsNameLength,
4804                                           OCI_DEFAULT) != OCI_SUCCESS) &&
4805                          OCIServerAttach(db.oci_server, db.oci_error,
4806                                          (OraText *) connectData.connectStringService,
4807                                          (sb4) connectData.connectStringServiceLength,
4808                                          OCI_DEFAULT) != OCI_SUCCESS &&
4809                          OCIServerAttach(db.oci_server, db.oci_error,
4810                                          (OraText *) connectData.connectStringSid,
4811                                          (sb4) connectData.connectStringSidLength,
4812                                          OCI_DEFAULT) != OCI_SUCCESS) {
4813                 setDbErrorMsg("sqlOpenOci", "OCIServerAttach", db.oci_error);
4814                 logError(printf("sqlOpenOci: OCIServerAttach(*, \"%s\", " FMT_U_MEM ", OCI_DEFAULT):\n%s\n",
4815                                 connectData.connectStringService,
4816                                 connectData.connectStringServiceLength, dbError.message););
4817                 err_info = DATABASE_ERROR;
4818                 sqlClose((databaseType) &db);
4819                 database = NULL;
4820               } else if (OCIAttrSet(db.oci_service_context, OCI_HTYPE_SVCCTX,
4821                                     db.oci_server, (ub4) 0,
4822                                     OCI_ATTR_SERVER, db.oci_error) != OCI_SUCCESS) {
4823                 setDbErrorMsg("sqlOpenOci", "OCIAttrSet", db.oci_error);
4824                 logError(printf("sqlOpenOci: OCIAttrSet OCI_ATTR_SERVER:\n%s\n",
4825                                 dbError.message););
4826                 err_info = DATABASE_ERROR;
4827                 sqlClose((databaseType) &db);
4828                 database = NULL;
4829               } else if (OCIAttrSet(db.oci_session, OCI_HTYPE_SESSION,
4830                                     user8, (ub4) user8Length,
4831                                     OCI_ATTR_USERNAME, db.oci_error) != OCI_SUCCESS) {
4832                 setDbErrorMsg("sqlOpenOci", "OCIAttrSet", db.oci_error);
4833                 logError(printf("sqlOpenOci: OCIAttrSet OCI_ATTR_USERNAME:\n%s\n",
4834                                 dbError.message););
4835                 err_info = DATABASE_ERROR;
4836                 sqlClose((databaseType) &db);
4837                 database = NULL;
4838               } else if (OCIAttrSet(db.oci_session, OCI_HTYPE_SESSION,
4839                                     password8, (ub4) password8Length,
4840                                     OCI_ATTR_PASSWORD, db.oci_error) != OCI_SUCCESS) {
4841                 setDbErrorMsg("sqlOpenOci", "OCIAttrSet", db.oci_error);
4842                 logError(printf("sqlOpenOci: OCIAttrSet OCI_ATTR_PASSWORD:\n%s\n",
4843                                 dbError.message););
4844                 err_info = DATABASE_ERROR;
4845                 sqlClose((databaseType) &db);
4846                 database = NULL;
4847               } else if (OCISessionBegin(db.oci_service_context, db.oci_error, db.oci_session,
4848                                          OCI_CRED_RDBMS, OCI_DEFAULT) != OCI_SUCCESS) {
4849                 setDbErrorMsg("sqlOpenOci", "OCISessionBegin", db.oci_error);
4850                 logError(printf("sqlOpenOci: OCISessionBegin:\n%s\n",
4851                                 dbError.message););
4852                 err_info = DATABASE_ERROR;
4853                 sqlClose((databaseType) &db);
4854                 database = NULL;
4855               } else if (OCIAttrSet(db.oci_service_context, OCI_HTYPE_SVCCTX,
4856                                     db.oci_session, (ub4) 0,
4857                                     OCI_ATTR_SESSION, db.oci_error) != OCI_SUCCESS) {
4858                 setDbErrorMsg("sqlOpenOci", "OCIAttrSet", db.oci_error);
4859                 logError(printf("sqlOpenOci: OCIAttrSet OCI_ATTR_SESSION:\n%s\n",
4860                                 dbError.message););
4861                 err_info = DATABASE_ERROR;
4862                 sqlClose((databaseType) &db);
4863                 database = NULL;
4864               } else if (unlikely(!setupFuncTable() ||
4865                                   !ALLOC_RECORD2(database, dbRecord,
4866                                                  count.database, count.database_bytes))) {
4867                 err_info = MEMORY_ERROR;
4868                 sqlClose((databaseType) &db);
4869                 database = NULL;
4870               } else {
4871                 memset(database, 0, sizeof(dbRecord));
4872                 database->usage_count = 1;
4873                 database->sqlFunc = sqlFunc;
4874                 database->driver = DB_CATEGORY_OCI;
4875                 database->oci_environment     = db.oci_environment;
4876                 database->oci_server          = db.oci_server;
4877                 database->oci_error           = db.oci_error;
4878                 database->oci_session         = db.oci_session;
4879                 database->oci_service_context = db.oci_service_context;
4880                 database->charSetId           = db.charSetId;
4881                 database->autoCommit = TRUE;
4882               } /* if */
4883               free_cstri8(password8, password);
4884             } /* if */
4885             free_cstri8(user8, user);
4886           } /* if */
4887           UNALLOC_CSTRI(connectData.tnsName, connectData.tnsNameLength);
4888           UNALLOC_CSTRI(connectData.connectStringService, connectData.connectStringServiceLength);
4889           UNALLOC_CSTRI(connectData.connectStringSid, connectData.connectStringSidLength);
4890         } /* if */
4891         free_cstri8(dbName8, dbName);
4892       } /* if */
4893       free_cstri8(host8, host);
4894     } /* if */
4895     if (unlikely(err_info != OKAY_NO_ERROR)) {
4896       raise_error(err_info);
4897     } /* if */
4898     logFunction(printf("sqlOpenOci --> " FMT_U_MEM "\n",
4899                        (memSizeType) database););
4900     return (databaseType) database;
4901   } /* sqlOpenOci */
4902 
4903 #else
4904 
4905 
4906 
sqlOpenOci(const const_striType host,intType port,const const_striType dbName,const const_striType user,const const_striType password)4907 databaseType sqlOpenOci (const const_striType host, intType port,
4908     const const_striType dbName, const const_striType user,
4909     const const_striType password)
4910 
4911   { /* sqlOpenOci */
4912     logError(printf("sqlOpenOci(\"%s\", ",
4913                     striAsUnquotedCStri(host));
4914              printf(FMT_D ", \"%s\", ",
4915                     port, striAsUnquotedCStri(dbName));
4916              printf("\"%s\", ", striAsUnquotedCStri(user));
4917              printf("\"%s\"): OCI driver not present.\n",
4918                     striAsUnquotedCStri(password)););
4919     raise_error(RANGE_ERROR);
4920     return NULL;
4921   } /* sqlOpenOci */
4922 
4923 #endif
4924