1 /********************************************************************/
2 /* */
3 /* sql_rtl.c Database access functions. */
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_rtl.c */
27 /* Changes: 2014, 2015, 2017 - 2020 Thomas Mertes */
28 /* Content: Database access functions. */
29 /* */
30 /********************************************************************/
31
32 #define LOG_FUNCTIONS 0
33 #define VERBOSE_EXCEPTIONS 0
34
35 #include "version.h"
36
37 #include "stdio.h"
38 #include "math.h"
39 #include "float.h"
40
41 #include "common.h"
42 #include "data_rtl.h"
43 #include "striutl.h"
44 #include "flt_rtl.h"
45 #include "big_drv.h"
46 #include "rtl_err.h"
47 #include "sql_base.h"
48 #include "sql_drv.h"
49
50 #undef EXTERN
51 #define EXTERN
52 #include "sql_rtl.h"
53
54
55 #define ENCODE_INFINITY 0
56 #define ENCODE_NAN 0
57
58
59 typedef struct dbStruct {
60 uintType usage_count;
61 sqlFuncType sqlFunc;
62 intType driver;
63 } dbRecord, *dbType;
64
65 typedef struct preparedStmtStruct {
66 uintType usage_count;
67 sqlFuncType sqlFunc;
68 } preparedStmtRecord, *preparedStmtType;
69
70
71
72 /**
73 * Bind a bigInteger parameter to a prepared SQL statement.
74 * @param sqlStatement Prepared statement.
75 * @param pos Position of the bind variable (starting with 1).
76 * @param value Value for the binding.
77 * @exception RANGE_ERROR If the statement was not prepared or
78 * if 'pos' is negative or too big or
79 * if 'value' cannot be converted.
80 * @exception DATABASE_ERROR If a database function fails.
81 */
sqlBindBigInt(sqlStmtType sqlStatement,intType pos,const const_bigIntType value)82 void sqlBindBigInt (sqlStmtType sqlStatement, intType pos,
83 const const_bigIntType value)
84
85 { /* sqlBindBigInt */
86 logFunction(printf("sqlBindBigInt(" FMT_U_MEM ", " FMT_D ", %s)\n",
87 (memSizeType) sqlStatement, pos, bigHexCStri(value)););
88 if (unlikely(sqlStatement == NULL ||
89 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
90 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindBigInt == NULL)) {
91 logError(printf("sqlBindBigInt(" FMT_U_MEM ", " FMT_D ", *): "
92 "SQL statement not okay.\n",
93 (memSizeType) sqlStatement, pos););
94 raise_error(RANGE_ERROR);
95 } else {
96 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindBigInt(sqlStatement, pos, value);
97 } /* if */
98 } /* sqlBindBigInt */
99
100
101
102 /**
103 * Bind a bigRational parameter to a prepared SQL statement.
104 * @param sqlStatement Prepared statement.
105 * @param pos Position of the bind variable (starting with 1).
106 * @param numerator Numerator of the Value for the binding.
107 * @param denominator Denominator of the Value for the binding.
108 * @exception RANGE_ERROR If the statement was not prepared or
109 * if 'pos' is negative or too big or
110 * if the big rational cannot be converted.
111 * @exception DATABASE_ERROR If a database function fails.
112 */
sqlBindBigRat(sqlStmtType sqlStatement,intType pos,const const_bigIntType numerator,const const_bigIntType denominator)113 void sqlBindBigRat (sqlStmtType sqlStatement, intType pos,
114 const const_bigIntType numerator, const const_bigIntType denominator)
115
116 { /* sqlBindBigRat */
117 logFunction(printf("sqlBindBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s)\n",
118 (memSizeType) sqlStatement, pos,
119 bigHexCStri(numerator), bigHexCStri(denominator)););
120 if (unlikely(sqlStatement == NULL ||
121 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
122 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindBigRat == NULL)) {
123 logError(printf("sqlBindBigRat(" FMT_U_MEM ", " FMT_D ", *): "
124 "SQL statement not okay.\n",
125 (memSizeType) sqlStatement, pos););
126 raise_error(RANGE_ERROR);
127 #if !ENCODE_INFINITY && !ENCODE_NAN
128 } else if (unlikely(bigEqSignedDigit(denominator, 0))) {
129 raise_error(RANGE_ERROR);
130 #else
131 #if !ENCODE_INFINITY
132 } else if (unlikely(bigEqSignedDigit(denominator, 0) && !bigEqSignedDigit(numerator, 0))) {
133 raise_error(RANGE_ERROR);
134 #endif
135 #if !ENCODE_NAN
136 } else if (unlikely(bigEqSignedDigit(denominator, 0) && bigEqSignedDigit(numerator, 0))) {
137 raise_error(RANGE_ERROR);
138 #endif
139 #endif
140 } else {
141 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindBigRat(sqlStatement, pos,
142 numerator, denominator);
143 } /* if */
144 } /* sqlBindBigRat */
145
146
147
148 /**
149 * Bind a boolean parameter to a prepared SQL statement.
150 * @param sqlStatement Prepared statement.
151 * @param pos Position of the bind variable (starting with 1).
152 * @param value Value for the binding.
153 * @exception RANGE_ERROR If the statement was not prepared or
154 * if 'pos' is negative or too big or
155 * if 'value' cannot be converted.
156 * @exception DATABASE_ERROR If a database function fails.
157 */
sqlBindBool(sqlStmtType sqlStatement,intType pos,boolType value)158 void sqlBindBool (sqlStmtType sqlStatement, intType pos, boolType value)
159
160 { /* sqlBindBool */
161 logFunction(printf("sqlBindBool(" FMT_U_MEM ", " FMT_D ", %s)\n",
162 (memSizeType) sqlStatement, pos, value ? "TRUE" : "FALSE"););
163 if (unlikely(sqlStatement == NULL ||
164 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
165 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindBool == NULL)) {
166 logError(printf("sqlBindBool(" FMT_U_MEM ", " FMT_D ", %s): "
167 "SQL statement not okay.\n",
168 (memSizeType) sqlStatement, pos, value ? "TRUE" : "FALSE"););
169 raise_error(RANGE_ERROR);
170 } else {
171 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindBool(sqlStatement, pos, value);
172 } /* if */
173 } /* sqlBindBool */
174
175
176
177 /**
178 * Bind a bstring parameter to a prepared SQL statement.
179 * @param sqlStatement Prepared statement.
180 * @param pos Position of the bind variable (starting with 1).
181 * @param bstri Value for the binding.
182 * @exception RANGE_ERROR If the statement was not prepared or
183 * if 'pos' is negative or too big or
184 * if 'bstri' cannot be converted.
185 * @exception DATABASE_ERROR If a database function fails.
186 */
sqlBindBStri(sqlStmtType sqlStatement,intType pos,const const_bstriType bstri)187 void sqlBindBStri (sqlStmtType sqlStatement, intType pos,
188 const const_bstriType bstri)
189
190 { /* sqlBindBStri */
191 logFunction(printf("sqlBindBStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
192 (memSizeType) sqlStatement, pos, bstriAsUnquotedCStri(bstri)););
193 if (unlikely(sqlStatement == NULL ||
194 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
195 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindBStri == NULL)) {
196 logError(printf("sqlBindBStri(" FMT_U_MEM ", " FMT_D ", \"%s\"): "
197 "SQL statement not okay.\n",
198 (memSizeType) sqlStatement, pos, bstriAsUnquotedCStri(bstri)););
199 raise_error(RANGE_ERROR);
200 } else {
201 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindBStri(sqlStatement, pos, bstri);
202 } /* if */
203 } /* sqlBindBStri */
204
205
206
207 /**
208 * Bind a duration parameter to a prepared SQL statement.
209 * @param sqlStatement Prepared statement.
210 * @param pos Position of the bind variable (starting with 1).
211 * @exception RANGE_ERROR If the statement was not prepared or
212 * if 'pos' is negative or too big or
213 * if the duration cannot be converted.
214 * @exception DATABASE_ERROR If a database function fails.
215 */
sqlBindDuration(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second)216 void sqlBindDuration (sqlStmtType sqlStatement, intType pos,
217 intType year, intType month, intType day, intType hour,
218 intType minute, intType second, intType micro_second)
219
220 { /* sqlBindDuration */
221 logFunction(printf("sqlBindDuration(" FMT_U_MEM ", " FMT_D ", "
222 F_D(04) "-" F_D(02) "-" F_D(02) " "
223 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ")\n",
224 (memSizeType) sqlStatement, pos,
225 year, month, day,
226 hour, minute, second, micro_second););
227 if (unlikely(sqlStatement == NULL ||
228 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
229 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindDuration == NULL)) {
230 logError(printf("sqlBindDuration(" FMT_U_MEM ", " FMT_D ", "
231 F_D(04) "-" F_D(02) "-" F_D(02) " "
232 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) "): "
233 "SQL statement not okay.\n",
234 (memSizeType) sqlStatement, pos,
235 year, month, day,
236 hour, minute, second, micro_second););
237 raise_error(RANGE_ERROR);
238 } else {
239 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindDuration(sqlStatement, pos,
240 year, month, day, hour, minute, second, micro_second);
241 } /* if */
242 } /* sqlBindDuration */
243
244
245
246 /**
247 * Bind a float parameter to a prepared SQL statement.
248 * @param sqlStatement Prepared statement.
249 * @param pos Position of the bind variable (starting with 1).
250 * @param value Value for the binding.
251 * @exception RANGE_ERROR If the statement was not prepared or
252 * if 'pos' is negative or too big or
253 * if 'value' cannot be converted.
254 * @exception DATABASE_ERROR If a database function fails.
255 */
sqlBindFloat(sqlStmtType sqlStatement,intType pos,floatType value)256 void sqlBindFloat (sqlStmtType sqlStatement, intType pos, floatType value)
257
258 { /* sqlBindFloat */
259 logFunction(printf("sqlBindFloat(" FMT_U_MEM ", " FMT_D ", " FMT_E ")\n",
260 (memSizeType) sqlStatement, pos, value););
261 if (unlikely(sqlStatement == NULL ||
262 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
263 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindFloat == NULL)) {
264 logError(printf("sqlBindFloat(" FMT_U_MEM ", " FMT_D ", " FMT_E "): "
265 "SQL statement not okay.\n",
266 (memSizeType) sqlStatement, pos, value););
267 raise_error(RANGE_ERROR);
268 #if !ENCODE_INFINITY
269 } else if (unlikely(value == POSITIVE_INFINITY || value == NEGATIVE_INFINITY)) {
270 raise_error(RANGE_ERROR);
271 #endif
272 #if !ENCODE_NAN
273 } else if (unlikely(os_isnan(value))) {
274 raise_error(RANGE_ERROR);
275 #endif
276 } else {
277 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindFloat(sqlStatement, pos, value);
278 } /* if */
279 } /* sqlBindFloat */
280
281
282
283 /**
284 * Bind an integer parameter to a prepared SQL statement.
285 * @param sqlStatement Prepared statement.
286 * @param pos Position of the bind variable (starting with 1).
287 * @param value Value for the binding.
288 * @exception RANGE_ERROR If the statement was not prepared or
289 * if 'pos' is negative or too big or
290 * if 'value' cannot be converted.
291 * @exception DATABASE_ERROR If a database function fails.
292 */
sqlBindInt(sqlStmtType sqlStatement,intType pos,intType value)293 void sqlBindInt (sqlStmtType sqlStatement, intType pos, intType value)
294
295 { /* sqlBindInt */
296 logFunction(printf("sqlBindInt(" FMT_U_MEM ", " FMT_D ", " FMT_D ")\n",
297 (memSizeType) sqlStatement, pos, value););
298 if (unlikely(sqlStatement == NULL ||
299 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
300 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindInt == NULL)) {
301 logError(printf("sqlBindInt(" FMT_U_MEM ", " FMT_D ", " FMT_D "): "
302 "SQL statement not okay.\n",
303 (memSizeType) sqlStatement, pos, value););
304 raise_error(RANGE_ERROR);
305 } else {
306 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindInt(sqlStatement, pos, value);
307 } /* if */
308 } /* sqlBindInt */
309
310
311
312 /**
313 * Bind a NULL parameter to a prepared SQL statement.
314 * @param sqlStatement Prepared statement.
315 * @param pos Position of the bind variable (starting with 1).
316 * @exception RANGE_ERROR If the statement was not prepared or
317 * if 'pos' is negative or too big.
318 * @exception DATABASE_ERROR If a database function fails.
319 */
sqlBindNull(sqlStmtType sqlStatement,intType pos)320 void sqlBindNull (sqlStmtType sqlStatement, intType pos)
321
322 { /* sqlBindNull */
323 logFunction(printf("sqlBindNull(" FMT_U_MEM ", " FMT_D ")\n",
324 (memSizeType) sqlStatement, pos););
325 if (unlikely(sqlStatement == NULL ||
326 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
327 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindNull == NULL)) {
328 logError(printf("sqlBindNull(" FMT_U_MEM ", " FMT_D "): "
329 "SQL statement not okay.\n",
330 (memSizeType) sqlStatement, pos););
331 raise_error(RANGE_ERROR);
332 } else {
333 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindNull(sqlStatement, pos);
334 } /* if */
335 } /* sqlBindNull */
336
337
338
339 /**
340 * Bind a string parameter to a prepared SQL statement.
341 * @param sqlStatement Prepared statement.
342 * @param pos Position of the bind variable (starting with 1).
343 * @param stri Value for the binding.
344 * @exception RANGE_ERROR If the statement was not prepared or
345 * if 'pos' is negative or too big or
346 * if 'stri' cannot be converted.
347 * @exception DATABASE_ERROR If a database function fails.
348 */
sqlBindStri(sqlStmtType sqlStatement,intType pos,const const_striType stri)349 void sqlBindStri (sqlStmtType sqlStatement, intType pos,
350 const const_striType stri)
351
352 { /* sqlBindStri */
353 logFunction(printf("sqlBindStri(" FMT_U_MEM ", " FMT_D ", \"%s\")\n",
354 (memSizeType) sqlStatement, pos, striAsUnquotedCStri(stri)););
355 if (unlikely(sqlStatement == NULL ||
356 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
357 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindStri == NULL)) {
358 logError(printf("sqlBindStri(" FMT_U_MEM ", " FMT_D ", \"%s\"): "
359 "SQL statement not okay.\n",
360 (memSizeType) sqlStatement, pos, striAsUnquotedCStri(stri)););
361 raise_error(RANGE_ERROR);
362 } else {
363 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindStri(sqlStatement, pos, stri);
364 } /* if */
365 } /* sqlBindStri */
366
367
368
369 /**
370 * Bind a time parameter to a prepared SQL statement.
371 * @param sqlStatement Prepared statement.
372 * @param pos Position of the bind variable (starting with 1).
373 * @exception RANGE_ERROR If the statement was not prepared or
374 * if 'pos' is negative or too big or
375 * if the time cannot be converted.
376 * @exception DATABASE_ERROR If a database function fails.
377 */
sqlBindTime(sqlStmtType sqlStatement,intType pos,intType year,intType month,intType day,intType hour,intType minute,intType second,intType micro_second,intType time_zone)378 void sqlBindTime (sqlStmtType sqlStatement, intType pos,
379 intType year, intType month, intType day, intType hour,
380 intType minute, intType second, intType micro_second,
381 intType time_zone)
382
383 { /* sqlBindTime */
384 logFunction(printf("sqlBindTime(" FMT_U_MEM ", " FMT_D ", "
385 F_D(04) "-" F_D(02) "-" F_D(02) " "
386 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ", "
387 FMT_D ")\n",
388 (memSizeType) sqlStatement, pos,
389 year, month, day,
390 hour, minute, second, micro_second,
391 time_zone););
392 if (unlikely(sqlStatement == NULL ||
393 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
394 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindTime == NULL)) {
395 logError(printf("sqlBindTime(" FMT_U_MEM ", " FMT_D ", "
396 F_D(04) "-" F_D(02) "-" F_D(02) " "
397 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) ", "
398 FMT_D "): "
399 "SQL statement not okay.\n",
400 (memSizeType) sqlStatement, pos,
401 year, month, day,
402 hour, minute, second, micro_second,
403 time_zone););
404 raise_error(RANGE_ERROR);
405 } else {
406 ((preparedStmtType) sqlStatement)->sqlFunc->sqlBindTime(sqlStatement, pos,
407 year, month, day, hour, minute, second, micro_second, time_zone);
408 } /* if */
409 } /* sqlBindTime */
410
411
412
413 /**
414 * Close the specified database 'database'.
415 * @param database Database to be closed.
416 * @exception RANGE_ERROR If the database was not open.
417 */
sqlClose(databaseType database)418 void sqlClose (databaseType database)
419
420 { /* sqlClose */
421 logFunction(printf("sqlClose(" FMT_U_MEM ")\n",
422 (memSizeType) database););
423 if (unlikely(database == NULL ||
424 ((dbType) database)->sqlFunc == NULL ||
425 ((dbType) database)->sqlFunc->sqlClose == NULL)) {
426 logError(printf("sqlClose(" FMT_U_MEM "): Database not okay.\n",
427 (memSizeType) database););
428 raise_error(RANGE_ERROR);
429 } else {
430 ((dbType) database)->sqlFunc->sqlClose(database);
431 } /* if */
432 } /* sqlClose */
433
434
435
436 /**
437 * Get the specified column of fetched data as bigInteger.
438 * If the column data is NULL it is interpreted as 0_.
439 * The function sqlIsNull can distinguish NULL from 0_.
440 * @param sqlStatement Prepared statement for which data was fetched.
441 * @param column Number of the column (starting with 1).
442 * @return the column data converted to a bigInteger, and
443 * 0_ if the column data is NULL.
444 * @exception RANGE_ERROR If the statement was not prepared or
445 * if no data was successfully fetched or
446 * if the specified column does not exist or
447 * if the column cannot be converted.
448 * @exception DATABASE_ERROR If a database function fails.
449 */
sqlColumnBigInt(sqlStmtType sqlStatement,intType column)450 bigIntType sqlColumnBigInt (sqlStmtType sqlStatement, intType column)
451
452 {
453 bigIntType columnValue;
454
455 /* sqlColumnBigInt */
456 logFunction(printf("sqlColumnBigInt(" FMT_U_MEM ", " FMT_D ")\n",
457 (memSizeType) sqlStatement, column););
458 if (unlikely(sqlStatement == NULL ||
459 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
460 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnBigInt == NULL)) {
461 logError(printf("sqlColumnBigInt(" FMT_U_MEM ", " FMT_D "): "
462 "SQL statement not okay.\n",
463 (memSizeType) sqlStatement, column););
464 raise_error(RANGE_ERROR);
465 columnValue = NULL;
466 } else {
467 columnValue = ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnBigInt(
468 sqlStatement, column);
469 } /* if */
470 logFunction(printf("sqlColumnBigInt --> %s\n", bigHexCStri(columnValue)););
471 return columnValue;
472 } /* sqlColumnBigInt */
473
474
475
476 /**
477 * Get the specified column of fetched data as bigRational.
478 * If the column data is NULL it is interpreted as 0_/1_.
479 * The function sqlIsNull can distinguish NULL from 0_/1_.
480 * @param sqlStatement Prepared statement for which data was fetched.
481 * @param column Number of the column (starting with 1).
482 * @param numerator Numerator of the column data.
483 * Set to 0_ if the column data is NULL
484 * @param denominator Denominator of the column data.
485 * Set to 1_ if the column data is NULL.
486 * @exception RANGE_ERROR If the statement was not prepared or
487 * if no data was successfully fetched or
488 * if the specified column does not exist or
489 * if the column cannot be converted.
490 * @exception DATABASE_ERROR If a database function fails.
491 */
sqlColumnBigRat(sqlStmtType sqlStatement,intType column,bigIntType * numerator,bigIntType * denominator)492 void sqlColumnBigRat (sqlStmtType sqlStatement, intType column,
493 bigIntType *numerator, bigIntType *denominator)
494
495 {
496 bigIntType oldNumerator;
497 bigIntType oldDenominator;
498
499 /* sqlColumnBigRat */
500 logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", *, *)\n",
501 (memSizeType) sqlStatement, column););
502 if (unlikely(sqlStatement == NULL ||
503 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
504 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnBigRat == NULL)) {
505 logError(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", *, *): "
506 "SQL statement not okay.\n",
507 (memSizeType) sqlStatement, column););
508 raise_error(RANGE_ERROR);
509 } else {
510 oldNumerator = *numerator;
511 oldDenominator = *denominator;
512 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnBigRat(sqlStatement, column,
513 numerator, denominator);
514 if (oldNumerator != *numerator) {
515 bigDestr(oldNumerator);
516 } /* if */
517 if (oldDenominator != *denominator) {
518 bigDestr(oldDenominator);
519 } /* if */
520 } /* if */
521 logFunction(printf("sqlColumnBigRat(" FMT_U_MEM ", " FMT_D ", %s, %s) -->\n",
522 (memSizeType) sqlStatement, column,
523 bigHexCStri(*numerator), bigHexCStri(*denominator)););
524 } /* sqlColumnBigRat */
525
526
527
528 /**
529 * Get the specified column of fetched data as boolean.
530 * If the column data is NULL it is interpreted as FALSE.
531 * The function sqlIsNull can distinguish NULL from FALSE.
532 * @param sqlStatement Prepared statement for which data was fetched.
533 * @param column Number of the column (starting with 1).
534 * @return the column data converted to a boolean, and
535 * FALSE if the column data is NULL.
536 * @exception RANGE_ERROR If the statement was not prepared or
537 * if no data was successfully fetched or
538 * if the specified column does not exist or
539 * if the column cannot be converted.
540 * @exception DATABASE_ERROR If a database function fails.
541 */
sqlColumnBool(sqlStmtType sqlStatement,intType column)542 boolType sqlColumnBool (sqlStmtType sqlStatement, intType column)
543
544 {
545 boolType columnValue;
546
547 /* sqlColumnBool */
548 logFunction(printf("sqlColumnBool(" FMT_U_MEM ", " FMT_D ")\n",
549 (memSizeType) sqlStatement, column););
550 if (unlikely(sqlStatement == NULL ||
551 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
552 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnBool == NULL)) {
553 logError(printf("sqlColumnBool(" FMT_U_MEM ", " FMT_D "): "
554 "SQL statement not okay.\n",
555 (memSizeType) sqlStatement, column););
556 raise_error(RANGE_ERROR);
557 columnValue = FALSE;
558 } else {
559 columnValue = ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnBool(
560 sqlStatement, column);
561 } /* if */
562 logFunction(printf("sqlColumnBool --> %s\n", columnValue ? "TRUE" : "FALSE"););
563 return columnValue;
564 } /* sqlColumnBool */
565
566
567
568 /**
569 * Get the specified column of fetched data as bstring.
570 * If the column data is NULL it is interpreted as empty bstring.
571 * The function sqlIsNull can distinguish NULL from an empty bstring.
572 * @param sqlStatement Prepared statement for which data was fetched.
573 * @param column Number of the column (starting with 1).
574 * @return the column data converted to a bstring, and
575 * an empty bstring if the column data is NULL.
576 * @exception RANGE_ERROR If the statement was not prepared or
577 * if no data was successfully fetched or
578 * if the specified column does not exist or
579 * if the column cannot be converted.
580 * @exception DATABASE_ERROR If a database function fails.
581 */
sqlColumnBStri(sqlStmtType sqlStatement,intType column)582 bstriType sqlColumnBStri (sqlStmtType sqlStatement, intType column)
583
584 {
585 bstriType columnValue;
586
587 /* sqlColumnBStri */
588 logFunction(printf("sqlColumnBStri(" FMT_U_MEM ", " FMT_D ")\n",
589 (memSizeType) sqlStatement, column););
590 if (unlikely(sqlStatement == NULL ||
591 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
592 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnBStri == NULL)) {
593 logError(printf("sqlColumnBStri(" FMT_U_MEM ", " FMT_D "): "
594 "SQL statement not okay.\n",
595 (memSizeType) sqlStatement, column););
596 raise_error(RANGE_ERROR);
597 columnValue = NULL;
598 } else {
599 columnValue = ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnBStri(
600 sqlStatement, column);
601 } /* if */
602 logFunction(printf("sqlColumnBStri --> \"%s\"\n",
603 bstriAsUnquotedCStri(columnValue)););
604 return columnValue;
605 } /* sqlColumnBStri */
606
607
608
609 /**
610 * Get the specified column of fetched data as duration.
611 * If the column data is NULL it is interpreted as empty duration.
612 * The function sqlIsNull can distinguish NULL from an empty duration.
613 * @param sqlStatement Prepared statement for which data was fetched.
614 * @param column Number of the column (starting with 1).
615 * @exception RANGE_ERROR If the statement was not prepared or
616 * if no data was successfully fetched or
617 * if the specified column does not exist or
618 * if the column cannot be converted.
619 * @exception DATABASE_ERROR If a database function fails.
620 */
sqlColumnDuration(sqlStmtType sqlStatement,intType column,intType * year,intType * month,intType * day,intType * hour,intType * minute,intType * second,intType * micro_second)621 void sqlColumnDuration (sqlStmtType sqlStatement, intType column,
622 intType *year, intType *month, intType *day, intType *hour,
623 intType *minute, intType *second, intType *micro_second)
624
625 { /* sqlColumnDuration */
626 logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ", *)\n",
627 (memSizeType) sqlStatement, column););
628 if (unlikely(sqlStatement == NULL ||
629 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
630 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnDuration == NULL)) {
631 logError(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ", *): "
632 "SQL statement not okay.\n",
633 (memSizeType) sqlStatement, column););
634 raise_error(RANGE_ERROR);
635 } else {
636 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnDuration(sqlStatement, column,
637 year, month, day, hour, minute, second, micro_second);
638 } /* if */
639 logFunction(printf("sqlColumnDuration(" FMT_U_MEM ", " FMT_D ", "
640 F_D(04) "-" F_D(02) "-" F_D(02) " "
641 F_D(02) ":" F_D(02) ":" F_D(02) "."
642 F_D(06) ") -->\n",
643 (memSizeType) sqlStatement, column,
644 *year, *month, *day, *hour, *minute, *second,
645 *micro_second););
646 } /* sqlColumnDuration */
647
648
649
650 /**
651 * Get the specified column of fetched data as float.
652 * If the column data is NULL it is interpreted as 0.0.
653 * The function sqlIsNull can distinguish NULL from 0.0.
654 * @param sqlStatement Prepared statement for which data was fetched.
655 * @param column Number of the column (starting with 1).
656 * @return the column data converted to a float, and
657 * 0.0 if the column data is NULL.
658 * @exception RANGE_ERROR If the statement was not prepared or
659 * if no data was successfully fetched or
660 * if the specified column does not exist or
661 * if the column cannot be converted.
662 * @exception DATABASE_ERROR If a database function fails.
663 */
sqlColumnFloat(sqlStmtType sqlStatement,intType column)664 floatType sqlColumnFloat (sqlStmtType sqlStatement, intType column)
665
666 {
667 floatType columnValue;
668
669 /* sqlColumnFloat */
670 logFunction(printf("sqlColumnFloat(" FMT_U_MEM ", " FMT_D ")\n",
671 (memSizeType) sqlStatement, column););
672 if (unlikely(sqlStatement == NULL ||
673 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
674 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnFloat == NULL)) {
675 logError(printf("sqlColumnFloat(" FMT_U_MEM ", " FMT_D "): "
676 "SQL statement not okay.\n",
677 (memSizeType) sqlStatement, column););
678 raise_error(RANGE_ERROR);
679 columnValue = 0.0;
680 } else {
681 columnValue = ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnFloat(
682 sqlStatement, column);
683 } /* if */
684 logFunction(printf("sqlColumnFloat --> " FMT_E "\n", columnValue););
685 return columnValue;
686 } /* sqlColumnFloat */
687
688
689
690 /**
691 * Get the specified column of fetched data as integer.
692 * If the column data is NULL it is interpreted as 0.
693 * The function sqlIsNull can distinguish NULL from 0.
694 * @param sqlStatement Prepared statement for which data was fetched.
695 * @param column Number of the column (starting with 1).
696 * @return the column data converted to an integer, and
697 * 0 if the column data is NULL.
698 * @exception RANGE_ERROR If the statement was not prepared or
699 * if no data was successfully fetched or
700 * if the specified column does not exist or
701 * if the column cannot be converted.
702 * @exception DATABASE_ERROR If a database function fails.
703 */
sqlColumnInt(sqlStmtType sqlStatement,intType column)704 intType sqlColumnInt (sqlStmtType sqlStatement, intType column)
705
706 {
707 intType columnValue;
708
709 /* sqlColumnInt */
710 logFunction(printf("sqlColumnInt(" FMT_U_MEM ", " FMT_D ")\n",
711 (memSizeType) sqlStatement, column););
712 if (unlikely(sqlStatement == NULL ||
713 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
714 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnInt == NULL)) {
715 logError(printf("sqlColumnInt(" FMT_U_MEM ", " FMT_D "): "
716 "SQL statement not okay.\n",
717 (memSizeType) sqlStatement, column););
718 raise_error(RANGE_ERROR);
719 columnValue = 0;
720 } else {
721 columnValue = ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnInt(sqlStatement,
722 column);
723 } /* if */
724 logFunction(printf("sqlColumnInt --> " FMT_D "\n", columnValue););
725 return columnValue;
726 } /* sqlColumnInt */
727
728
729
730 /**
731 * Get the specified column of fetched data as string.
732 * If the column data is NULL it is interpreted as "".
733 * The function sqlIsNull can distinguish NULL from "".
734 * @param sqlStatement Prepared statement for which data was fetched.
735 * @param column Number of the column (starting with 1).
736 * @return the column data converted to a string, and
737 * "" if the column data is NULL.
738 * @exception RANGE_ERROR If the statement was not prepared or
739 * if no data was successfully fetched or
740 * if the specified column does not exist or
741 * if the column cannot be converted.
742 * @exception DATABASE_ERROR If a database function fails.
743 */
sqlColumnStri(sqlStmtType sqlStatement,intType column)744 striType sqlColumnStri (sqlStmtType sqlStatement, intType column)
745
746 {
747 striType columnValue;
748
749 /* sqlColumnStri */
750 logFunction(printf("sqlColumnStri(" FMT_U_MEM ", " FMT_D ")\n",
751 (memSizeType) sqlStatement, column););
752 if (unlikely(sqlStatement == NULL ||
753 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
754 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnStri == NULL)) {
755 logError(printf("sqlColumnStri(" FMT_U_MEM ", " FMT_D "): "
756 "SQL statement not okay.\n",
757 (memSizeType) sqlStatement, column););
758 raise_error(RANGE_ERROR);
759 columnValue = NULL;
760 } else {
761 columnValue = ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnStri(
762 sqlStatement, column);
763 } /* if */
764 logFunction(printf("sqlColumnStri --> \"%s\"\n", striAsUnquotedCStri(columnValue)););
765 return columnValue;
766 } /* sqlColumnStri */
767
768
769
770 /**
771 * Get the specified column of fetched data as time.
772 * If the column data is NULL it is interpreted as 0-01-01 00:00:00.
773 * The function sqlIsNull can distinguish NULL from 0-01-01 00:00:00.
774 * @param sqlStatement Prepared statement for which data was fetched.
775 * @param column Number of the column (starting with 1).
776 * @exception RANGE_ERROR If the statement was not prepared or
777 * if no data was successfully fetched or
778 * if the specified column does not exist or
779 * if the column cannot be converted.
780 * @exception DATABASE_ERROR If a database function fails.
781 */
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)782 void sqlColumnTime (sqlStmtType sqlStatement, intType column,
783 intType *year, intType *month, intType *day, intType *hour,
784 intType *minute, intType *second, intType *micro_second,
785 intType *time_zone, boolType *is_dst)
786
787 { /* sqlColumnTime */
788 logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", *)\n",
789 (memSizeType) sqlStatement, column););
790 if (unlikely(sqlStatement == NULL ||
791 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
792 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnTime == NULL)) {
793 logError(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", *): "
794 "SQL statement not okay.\n",
795 (memSizeType) sqlStatement, column););
796 raise_error(RANGE_ERROR);
797 } else {
798 ((preparedStmtType) sqlStatement)->sqlFunc->sqlColumnTime(sqlStatement, column,
799 year, month, day, hour, minute, second,
800 micro_second, time_zone, is_dst);
801 } /* if */
802 logFunction(printf("sqlColumnTime(" FMT_U_MEM ", " FMT_D ", "
803 F_D(04) "-" F_D(02) "-" F_D(02) " "
804 F_D(02) ":" F_D(02) ":" F_D(02) "."
805 F_D(06) ", " FMT_D ", %d) -->\n",
806 (memSizeType) sqlStatement, column,
807 *year, *month, *day, *hour, *minute, *second,
808 *micro_second, *time_zone, *is_dst););
809 } /* sqlColumnTime */
810
811
812
813 /**
814 * Execute a commit statement for the specified database 'database'.
815 */
sqlCommit(databaseType database)816 void sqlCommit (databaseType database)
817
818 { /* sqlCommit */
819 logFunction(printf("sqlCommit(" FMT_U_MEM ")\n",
820 (memSizeType) database););
821 if (unlikely(database == NULL ||
822 ((dbType) database)->sqlFunc == NULL ||
823 ((dbType) database)->sqlFunc->sqlCommit == NULL)) {
824 logError(printf("sqlCommit(" FMT_U_MEM "): Database not okay.\n",
825 (memSizeType) database););
826 raise_error(RANGE_ERROR);
827 } else {
828 ((dbType) database)->sqlFunc->sqlCommit(database);
829 } /* if */
830 logFunction(printf("sqlCommit -->\n"););
831 } /* sqlCommit */
832
833
834
835 /**
836 * Assign source to *dest.
837 * A copy function assumes that *dest contains a legal value.
838 * @exception MEMORY_ERROR Not enough memory to create dest.
839 */
sqlCpyDb(databaseType * const dest,const databaseType source)840 void sqlCpyDb (databaseType *const dest, const databaseType source)
841
842 {
843 dbType db_dest;
844 dbType db_source;
845
846 /* sqlCpyDb */
847 logFunction(printf("sqlCpyDb(" FMT_U_MEM ", " FMT_U_MEM ")\n",
848 (memSizeType) dest, (memSizeType) source););
849 db_dest = (dbType) *dest;
850 db_source = (dbType) source;
851 if (db_source != NULL) {
852 db_source->usage_count++;
853 } /* if */
854 if (db_dest != NULL) {
855 db_dest->usage_count--;
856 if (db_dest->usage_count == 0 &&
857 db_dest->sqlFunc != NULL &&
858 db_dest->sqlFunc->freeDatabase != NULL) {
859 /* printf("FREE %lx\n", (long unsigned int) db_dest); */
860 db_dest->sqlFunc->freeDatabase((databaseType) db_dest);
861 } /* if */
862 } /* if */
863 *dest = (databaseType) db_source;
864 } /* sqlCpyDb */
865
866
867
868 /**
869 * Reinterpret the generic parameters as databaseType and call sqlCpyDb.
870 * Function pointers in C programs generated by the Seed7 compiler
871 * may point to this function. This assures correct behaviour even
872 * if sizeof(genericType) != sizeof(databaseType).
873 */
sqlCpyDbGeneric(genericType * const dest,const genericType source)874 void sqlCpyDbGeneric (genericType *const dest, const genericType source)
875
876 { /* sqlCpyDbGeneric */
877 sqlCpyDb(&((rtlObjectType *) dest)->value.databaseValue,
878 ((const_rtlObjectType *) &source)->value.databaseValue);
879 } /* sqlCpyDbGeneric */
880
881
882
883 /**
884 * Assign source to *dest.
885 * A copy function assumes that *dest contains a legal value.
886 * @exception MEMORY_ERROR Not enough memory to create dest.
887 */
sqlCpyStmt(sqlStmtType * const dest,const sqlStmtType source)888 void sqlCpyStmt (sqlStmtType *const dest, const sqlStmtType source)
889
890 {
891 preparedStmtType statement_dest;
892 preparedStmtType statement_source;
893
894 /* sqlCpyStmt */
895 logFunction(printf("sqlCpyStmt(" FMT_U_MEM ", " FMT_U_MEM ")\n",
896 (memSizeType) dest, (memSizeType) source););
897 statement_dest = (preparedStmtType) *dest;
898 statement_source = (preparedStmtType) source;
899 if (statement_source != NULL) {
900 statement_source->usage_count++;
901 } /* if */
902 if (statement_dest != NULL) {
903 statement_dest->usage_count--;
904 if (statement_dest->usage_count == 0 &&
905 statement_dest->sqlFunc != NULL &&
906 statement_dest->sqlFunc->freePreparedStmt != NULL) {
907 /* printf("FREE %lx\n", (long unsigned int) statement_dest); */
908 statement_dest->sqlFunc->freePreparedStmt((sqlStmtType) statement_dest);
909 } /* if */
910 } /* if */
911 *dest = (sqlStmtType) statement_source;
912 } /* sqlCpyStmt */
913
914
915
916 /**
917 * Reinterpret the generic parameters as sqlStmtType and call sqlCpyStmt.
918 * Function pointers in C programs generated by the Seed7 compiler
919 * may point to this function. This assures correct behaviour even
920 * if sizeof(genericType) != sizeof(sqlStmtType).
921 */
sqlCpyStmtGeneric(genericType * const dest,const genericType source)922 void sqlCpyStmtGeneric (genericType *const dest, const genericType source)
923
924 { /* sqlCpyStmtGeneric */
925 sqlCpyStmt(&((rtlObjectType *) dest)->value.sqlStmtValue,
926 ((const_rtlObjectType *) &source)->value.sqlStmtValue);
927 } /* sqlCpyStmtGeneric */
928
929
930
931 /**
932 * Return a copy of source, that can be assigned to a new destination.
933 * It is assumed that the destination of the assignment is undefined.
934 * Create functions can be used to initialize Seed7 constants.
935 * @return a copy of source.
936 */
sqlCreateDb(const databaseType source)937 databaseType sqlCreateDb (const databaseType source)
938
939 { /* sqlCreateDb */
940 logFunction(printf("sqlCreateDb(" FMT_U_MEM ")\n",
941 (memSizeType) source););
942 if (source != NULL) {
943 ((dbType) source)->usage_count++;
944 } /* if */
945 return source;
946 } /* sqlCreateDb */
947
948
949
950 /**
951 * Generic Create function to be used via function pointers.
952 * Function pointers in C programs generated by the Seed7 compiler
953 * may point to this function. This assures correct behaviour even
954 * if sizeof(genericType) != sizeof(databaseType).
955 */
sqlCreateDbGeneric(const genericType from_value)956 genericType sqlCreateDbGeneric (const genericType from_value)
957
958 {
959 rtlObjectType result;
960
961 /* sqlCreateDbGeneric */
962 INIT_GENERIC_PTR(result.value.genericValue);
963 result.value.databaseValue =
964 sqlCreateDb(((const_rtlObjectType *) &from_value)->value.databaseValue);
965 return result.value.genericValue;
966 } /* sqlCreateDbGeneric */
967
968
969
970 /**
971 * Return a copy of source, that can be assigned to a new destination.
972 * It is assumed that the destination of the assignment is undefined.
973 * Create functions can be used to initialize Seed7 constants.
974 * @return a copy of source.
975 */
sqlCreateStmt(const sqlStmtType source)976 sqlStmtType sqlCreateStmt (const sqlStmtType source)
977
978 { /* sqlCreateStmt */
979 logFunction(printf("sqlCreateStmt(" FMT_U_MEM ")\n",
980 (memSizeType) source););
981 if (source != NULL) {
982 ((preparedStmtType) source)->usage_count++;
983 } /* if */
984 return source;
985 } /* sqlCreateStmt */
986
987
988
989 /**
990 * Generic Create function to be used via function pointers.
991 * Function pointers in C programs generated by the Seed7 compiler
992 * may point to this function. This assures correct behaviour even
993 * if sizeof(genericType) != sizeof(sqlStmtType).
994 */
sqlCreateStmtGeneric(const genericType from_value)995 genericType sqlCreateStmtGeneric (const genericType from_value)
996
997 {
998 rtlObjectType result;
999
1000 /* sqlCreateStmtGeneric */
1001 INIT_GENERIC_PTR(result.value.genericValue);
1002 result.value.sqlStmtValue =
1003 sqlCreateStmt(((const_rtlObjectType *) &from_value)->value.sqlStmtValue);
1004 return result.value.genericValue;
1005 } /* sqlCreateStmtGeneric */
1006
1007
1008
1009 /**
1010 * Maintain a usage count and free an unused database 'old_db'.
1011 * After a database is freed 'old_db' refers to not existing memory.
1012 * The memory where 'old_db' is stored can be freed after sqlDestrDb.
1013 */
sqlDestrDb(const databaseType old_db)1014 void sqlDestrDb (const databaseType old_db)
1015
1016 {
1017 dbType old_database;
1018
1019 /* sqlDestrDb */
1020 logFunction(printf("sqlDestrDb(" FMT_U_MEM ")\n",
1021 (memSizeType) old_db););
1022 old_database = (dbType) old_db;
1023 if (old_database != NULL) {
1024 old_database->usage_count--;
1025 if (old_database->usage_count == 0 &&
1026 old_database->sqlFunc != NULL &&
1027 old_database->sqlFunc->freeDatabase != NULL) {
1028 /* printf("FREE %lx\n", (long unsigned int) old_database); */
1029 old_database->sqlFunc->freeDatabase((databaseType) old_database);
1030 } /* if */
1031 } /* if */
1032 } /* sqlDestrDb */
1033
1034
1035
1036 /**
1037 * Generic Destr function to be used via function pointers.
1038 * Function pointers in C programs generated by the Seed7 compiler
1039 * may point to this function. This assures correct behaviour even
1040 * if sizeof(genericType) != sizeof(databaseType).
1041 */
sqlDestrDbGeneric(const genericType old_value)1042 void sqlDestrDbGeneric (const genericType old_value)
1043
1044 { /* sqlDestrDbGeneric */
1045 sqlDestrDb(((const_rtlObjectType *) &old_value)->value.databaseValue);
1046 } /* sqlDestrDbGeneric */
1047
1048
1049
1050 /**
1051 * Maintain a usage count and free an unused statement 'old_stmt'.
1052 * After a statement is freed 'old_stmt' refers to not existing memory.
1053 * The memory where 'old_stmt' is stored can be freed after sqlDestrStmt.
1054 */
sqlDestrStmt(const sqlStmtType old_stmt)1055 void sqlDestrStmt (const sqlStmtType old_stmt)
1056
1057 {
1058 preparedStmtType old_statement;
1059
1060 /* sqlDestrStmt */
1061 logFunction(printf("sqlDestrStmt(" FMT_U_MEM ")\n",
1062 (memSizeType) old_stmt););
1063 old_statement = (preparedStmtType) old_stmt;
1064 if (old_statement != NULL) {
1065 old_statement->usage_count--;
1066 if (old_statement->usage_count == 0 &&
1067 old_statement->sqlFunc != NULL &&
1068 old_statement->sqlFunc->freePreparedStmt != NULL) {
1069 /* printf("FREE %lx\n", (long unsigned int) old_statement); */
1070 old_statement->sqlFunc->freePreparedStmt((sqlStmtType) old_statement);
1071 } /* if */
1072 } /* if */
1073 } /* sqlDestrStmt */
1074
1075
1076
1077 /**
1078 * Generic Destr function to be used via function pointers.
1079 * Function pointers in C programs generated by the Seed7 compiler
1080 * may point to this function. This assures correct behaviour even
1081 * if sizeof(genericType) != sizeof(sqlStmtType).
1082 */
sqlDestrStmtGeneric(const genericType old_value)1083 void sqlDestrStmtGeneric (const genericType old_value)
1084
1085 { /* sqlDestrStmtGeneric */
1086 sqlDestrStmt(((const_rtlObjectType *) &old_value)->value.sqlStmtValue);
1087 } /* sqlDestrStmtGeneric */
1088
1089
1090
sqlDriver(databaseType database)1091 intType sqlDriver (databaseType database)
1092
1093 {
1094 intType driver;
1095
1096 /* sqlDriver */
1097 logFunction(printf("sqlDriver(" FMT_U_MEM ")\n",
1098 (memSizeType) database););
1099 if (unlikely(database == NULL)) {
1100 logError(printf("sqlDriver: Database is not open.\n"););
1101 raise_error(RANGE_ERROR);
1102 driver = 0;
1103 } else {
1104 driver = ((dbType) database)->driver;
1105 } /* if */
1106 logFunction(printf("sqlDriver --> " FMT_D "\n", driver););
1107 return driver;
1108 } /* sqlDriver */
1109
1110
1111
sqlErrCode(void)1112 intType sqlErrCode (void)
1113
1114 { /* sqlErrCode */
1115 return dbError.errorCode;
1116 } /* sqlErrCode */
1117
1118
1119
sqlErrDbFunc(void)1120 striType sqlErrDbFunc (void)
1121
1122 {
1123 striType dbFuncName;
1124
1125 /* sqlErrDbFunc */
1126 dbFuncName = cstri_to_stri(dbError.dbFuncName);
1127 if (unlikely(dbFuncName == NULL)) {
1128 raise_error(MEMORY_ERROR);
1129 } /* if */
1130 return dbFuncName;
1131 } /* sqlErrDbFunc */
1132
1133
1134
sqlErrLibFunc(void)1135 striType sqlErrLibFunc (void)
1136
1137 {
1138 striType funcName;
1139
1140 /* sqlErrLibFunc */
1141 funcName = cstri_to_stri(dbError.funcName);
1142 if (unlikely(funcName == NULL)) {
1143 raise_error(MEMORY_ERROR);
1144 } /* if */
1145 return funcName;
1146 } /* sqlErrLibFunc */
1147
1148
1149
sqlErrMessage(void)1150 striType sqlErrMessage (void)
1151
1152 {
1153 striType message;
1154
1155 /* sqlErrMessage */
1156 message = cstri8_or_cstri_to_stri(dbError.message);
1157 if (unlikely(message == NULL)) {
1158 raise_error(MEMORY_ERROR);
1159 } /* if */
1160 return message;
1161 } /* sqlErrMessage */
1162
1163
1164
1165 /**
1166 * Execute the specified prepared SQL statement.
1167 * Bind variable can be assigned with bind functions before
1168 * sqlExecute is called.
1169 * @param sqlStatement Prepared statement, which should be executed.
1170 * @exception DATABASE_ERROR If a database function fails.
1171 */
sqlExecute(sqlStmtType sqlStatement)1172 void sqlExecute (sqlStmtType sqlStatement)
1173
1174 { /* sqlExecute */
1175 logFunction(printf("sqlExecute(" FMT_U_MEM ")\n",
1176 (memSizeType) sqlStatement););
1177 if (sqlStatement == NULL) {
1178 /* Do nothing */
1179 } else if (unlikely(((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
1180 ((preparedStmtType) sqlStatement)->sqlFunc->sqlExecute == NULL)) {
1181 raise_error(RANGE_ERROR);
1182 } else {
1183 ((preparedStmtType) sqlStatement)->sqlFunc->sqlExecute(sqlStatement);
1184 } /* if */
1185 logFunction(printf("sqlExecute -->\n"););
1186 } /* sqlExecute */
1187
1188
1189
1190 /**
1191 * Fetch a row from the result data of an executed 'sqlStatement'.
1192 * After the 'sqlStatement' has been executed successfully the
1193 * function sqlFetch can be used to get the first and further
1194 * rows of the statements result data. The columns of the
1195 * result data can be obtained with the column functions.
1196 * @param sqlStatement Prepared statement, which has been executed.
1197 * @return TRUE if a row of result data could be fetched successfully.
1198 * FALSE if no more result data is available.
1199 * @exception DATABASE_ERROR If a database function fails.
1200 */
sqlFetch(sqlStmtType sqlStatement)1201 boolType sqlFetch (sqlStmtType sqlStatement)
1202
1203 {
1204 boolType fetchOkay;
1205
1206 /* sqlFetch */
1207 logFunction(printf("sqlFetch(" FMT_U_MEM ")\n",
1208 (memSizeType) sqlStatement););
1209 if (sqlStatement == NULL) {
1210 fetchOkay = FALSE;
1211 } else if (unlikely(((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
1212 ((preparedStmtType) sqlStatement)->sqlFunc->sqlFetch == NULL)) {
1213 raise_error(RANGE_ERROR);
1214 fetchOkay = FALSE;
1215 } else {
1216 fetchOkay = ((preparedStmtType) sqlStatement)->sqlFunc->sqlFetch(sqlStatement);
1217 } /* if */
1218 logFunction(printf("sqlFetch --> %d\n", fetchOkay););
1219 return fetchOkay;
1220 } /* sqlFetch */
1221
1222
1223
1224 /**
1225 * Get the current auto-commit mode for the specified database 'database'.
1226 */
sqlGetAutoCommit(databaseType database)1227 boolType sqlGetAutoCommit (databaseType database)
1228
1229 {
1230 boolType autoCommit;
1231
1232 /* sqlGetAutoCommit */
1233 logFunction(printf("sqlGetAutoCommit(" FMT_U_MEM ")\n",
1234 (memSizeType) database););
1235 if (unlikely(database == NULL ||
1236 ((dbType) database)->sqlFunc == NULL ||
1237 ((dbType) database)->sqlFunc->sqlGetAutoCommit == NULL)) {
1238 logError(printf("sqlGetAutoCommit(" FMT_U_MEM "): Database not okay.\n",
1239 (memSizeType) database););
1240 raise_error(RANGE_ERROR);
1241 autoCommit = FALSE;
1242 } else {
1243 autoCommit = ((dbType) database)->sqlFunc->sqlGetAutoCommit(database);
1244 } /* if */
1245 logFunction(printf("sqlGetAutoCommit --> %d\n", autoCommit););
1246 return autoCommit;
1247 } /* sqlGetAutoCommit */
1248
1249
1250
1251 /**
1252 * Determine if the specified column of fetched data is NULL.
1253 * @param sqlStatement Prepared statement for which data was fetched.
1254 * @param column Number of the column (starting with 1).
1255 * @return TRUE if the column data is NULL,
1256 * FALSE otherwise.
1257 * @exception RANGE_ERROR If the statement was not prepared or
1258 * if no data was successfully fetched or
1259 * if the specified column does not exist.
1260 */
sqlIsNull(sqlStmtType sqlStatement,intType column)1261 boolType sqlIsNull (sqlStmtType sqlStatement, intType column)
1262
1263 {
1264 boolType isNull;
1265
1266 /* sqlIsNull */
1267 logFunction(printf("sqlIsNull(" FMT_U_MEM ", " FMT_D ")\n",
1268 (memSizeType) sqlStatement, column););
1269 if (unlikely(sqlStatement == NULL ||
1270 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
1271 ((preparedStmtType) sqlStatement)->sqlFunc->sqlIsNull == NULL)) {
1272 raise_error(RANGE_ERROR);
1273 isNull = FALSE;
1274 } else {
1275 isNull = ((preparedStmtType) sqlStatement)->sqlFunc->sqlIsNull(sqlStatement,
1276 column);
1277 } /* if */
1278 logFunction(printf("sqlIsNull --> %s\n", isNull ? "TRUE" : "FALSE"););
1279 return isNull;
1280 } /* sqlIsNull */
1281
1282
1283
1284 /**
1285 * Create a prepared statement for the given 'database'.
1286 * @param database Database connection for which the prepared
1287 * statement should be created.
1288 * @param sqlStatementStri SQL statement in a string. For bind variables
1289 * use a question mark (?).
1290 * @exception RANGE_ERROR If the database is not open.
1291 */
sqlPrepare(databaseType database,const const_striType sqlStatementStri)1292 sqlStmtType sqlPrepare (databaseType database,
1293 const const_striType sqlStatementStri)
1294
1295 {
1296 sqlStmtType preparedStmt;
1297
1298 /* sqlPrepare */
1299 logFunction(printf("sqlPrepare(" FMT_U_MEM ", \"%s\")\n",
1300 (memSizeType) database,
1301 striAsUnquotedCStri(sqlStatementStri)););
1302 if (unlikely(database == NULL ||
1303 ((dbType) database)->sqlFunc == NULL ||
1304 ((dbType) database)->sqlFunc->sqlPrepare == NULL)) {
1305 logError(printf("sqlPrepare: Database is not open.\n"););
1306 raise_error(RANGE_ERROR);
1307 preparedStmt = NULL;
1308 } else {
1309 preparedStmt = ((dbType) database)->sqlFunc->sqlPrepare(database, sqlStatementStri);
1310 } /* if */
1311 logFunction(printf("sqlPrepare --> " FMT_U_MEM "\n",
1312 (memSizeType) preparedStmt););
1313 return preparedStmt;
1314 } /* sqlPrepare */
1315
1316
1317
1318 /**
1319 * Execute a rollback statement for the specified database 'database'.
1320 */
sqlRollback(databaseType database)1321 void sqlRollback (databaseType database)
1322
1323 { /* sqlRollback */
1324 logFunction(printf("sqlRollback(" FMT_U_MEM ")\n",
1325 (memSizeType) database););
1326 if (unlikely(database == NULL ||
1327 ((dbType) database)->sqlFunc == NULL ||
1328 ((dbType) database)->sqlFunc->sqlRollback == NULL)) {
1329 logError(printf("sqlRollback(" FMT_U_MEM "): Database not okay.\n",
1330 (memSizeType) database););
1331 raise_error(RANGE_ERROR);
1332 } else {
1333 ((dbType) database)->sqlFunc->sqlRollback(database);
1334 } /* if */
1335 logFunction(printf("sqlRollback -->\n"););
1336 } /* sqlRollback */
1337
1338
1339
1340 /**
1341 * Set the auto-commit mode for the specified database 'database'.
1342 */
sqlSetAutoCommit(databaseType database,boolType autoCommit)1343 void sqlSetAutoCommit (databaseType database, boolType autoCommit)
1344
1345 { /* sqlSetAutoCommit */
1346 logFunction(printf("sqlSetAutoCommit(" FMT_U_MEM ", %d)\n",
1347 (memSizeType) database, autoCommit););
1348 if (unlikely(database == NULL ||
1349 ((dbType) database)->sqlFunc == NULL ||
1350 ((dbType) database)->sqlFunc->sqlSetAutoCommit == NULL)) {
1351 raise_error(RANGE_ERROR);
1352 } else {
1353 ((dbType) database)->sqlFunc->sqlSetAutoCommit(database, autoCommit);
1354 } /* if */
1355 logFunction(printf("sqlSetAutoCommit --> %d\n", fetchOkay););
1356 } /* sqlSetAutoCommit */
1357
1358
1359
1360 /**
1361 * Return the number of columns in the result data of a ''statement''.
1362 * It is not necessary to ''execute'' the prepared statement, before
1363 * ''columnCount'' is called.
1364 * @param statement Prepared statement.
1365 */
sqlStmtColumnCount(sqlStmtType sqlStatement)1366 intType sqlStmtColumnCount (sqlStmtType sqlStatement)
1367
1368 {
1369 intType columnCount;
1370
1371 /* sqlStmtColumnCount */
1372 logFunction(printf("sqlStmtColumnCount(" FMT_U_MEM ")\n",
1373 (memSizeType) sqlStatement););
1374 if (unlikely(sqlStatement == NULL ||
1375 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
1376 ((preparedStmtType) sqlStatement)->sqlFunc->sqlStmtColumnCount == NULL)) {
1377 raise_error(RANGE_ERROR);
1378 columnCount = 0;
1379 } else {
1380 columnCount = ((preparedStmtType) sqlStatement)->sqlFunc->sqlStmtColumnCount(
1381 sqlStatement);
1382 } /* if */
1383 logFunction(printf("sqlStmtColumnCount --> " FMT_D "\n", columnCount););
1384 return columnCount;
1385 } /* sqlStmtColumnCount */
1386
1387
1388
sqlStmtColumnName(sqlStmtType sqlStatement,intType column)1389 striType sqlStmtColumnName (sqlStmtType sqlStatement, intType column)
1390
1391 {
1392 striType name;
1393
1394 /* sqlStmtColumnName */
1395 logFunction(printf("sqlStmtColumnName(" FMT_U_MEM ", " FMT_D ")\n",
1396 (memSizeType) sqlStatement, column););
1397 if (unlikely(sqlStatement == NULL ||
1398 ((preparedStmtType) sqlStatement)->sqlFunc == NULL ||
1399 ((preparedStmtType) sqlStatement)->sqlFunc->sqlStmtColumnName == NULL)) {
1400 raise_error(RANGE_ERROR);
1401 name = NULL;
1402 } else {
1403 name = ((preparedStmtType) sqlStatement)->sqlFunc->sqlStmtColumnName(sqlStatement,
1404 column);
1405 } /* if */
1406 logFunction(printf("sqlStmtColumnName --> \"%s\"\n",
1407 striAsUnquotedCStri(name)););
1408 return name;
1409 } /* sqlStmtColumnName */
1410