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