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 ¶m->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 ¶m->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 ¶m->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 ¶m->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 ¶m->bind_handle,
2744 preparedStmt->oci_error,
2745 (ub4) pos,
2746 param->buffer,
2747 (sb4) param->buffer_length,
2748 SQLT_BLOB,
2749 ¶m->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 ¶m->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 ¶m->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 ¶m->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 ¶m->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 ¶m->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 ¶m->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 ¶m->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 ¶m->bind_handle,
3097 preparedStmt->oci_error,
3098 (ub4) pos,
3099 NULL,
3100 0,
3101 SQLT_CHR,
3102 ¶m->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 ¶m->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 ¶m->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 ¶m->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