18
18
* USA.
19
19
*/
20
20
21
+ #include <assert.h>
21
22
#include <string.h>
22
23
#include <mysql.h>
23
24
#include <sqlite3.h>
30
31
31
32
struct db_stmt {
32
33
bool (* bind )(const struct db_stmt * stmt ,
33
- struct db_row * rows ,
34
- size_t n_rows );
35
- bool (* step )(const struct db_stmt * stmt , const char * signature , va_list ap );
34
+ struct db_row * rows );
35
+ bool (* step )(const struct db_stmt * stmt , va_list ap );
36
36
void (* finalize )(struct db_stmt * stmt );
37
+ const char * param_signature ;
38
+ const char * result_signature ;
37
39
};
38
40
39
41
struct db {
40
42
void (* disconnect )(struct db * db );
41
43
struct db_stmt * (* prepare )(const struct db * db ,
42
44
const char * sql ,
43
- const size_t sql_len );
45
+ const char * param_signature ,
46
+ const char * result_signature );
44
47
};
45
48
46
49
/* MySQL */
@@ -56,28 +59,23 @@ struct db_stmt_mysql {
56
59
MYSQL_BIND * param_bind ;
57
60
MYSQL_BIND * result_bind ;
58
61
bool must_execute_again ;
62
+ bool results_are_bound ;
63
+ MYSQL_BIND param_result_bind [];
59
64
};
60
65
61
66
static bool db_stmt_bind_mysql (const struct db_stmt * stmt ,
62
- struct db_row * rows ,
63
- size_t n_rows )
67
+ struct db_row * rows )
64
68
{
65
69
struct db_stmt_mysql * stmt_mysql = (struct db_stmt_mysql * )stmt ;
70
+ const char * signature = stmt -> param_signature ;
66
71
67
72
stmt_mysql -> must_execute_again = true;
73
+ mysql_stmt_reset (stmt_mysql -> stmt );
68
74
69
- if (!stmt_mysql -> param_bind ) {
70
- stmt_mysql -> param_bind = calloc (n_rows , sizeof (MYSQL_BIND ));
71
- if (!stmt_mysql -> param_bind )
72
- return false;
73
- } else {
74
- mysql_stmt_reset (stmt_mysql -> stmt );
75
- }
76
-
77
- for (size_t row = 0 ; row < n_rows && rows [row ].kind ; row ++ ) {
75
+ for (size_t row = 0 ; signature [row ]; row ++ ) {
78
76
MYSQL_BIND * param = & stmt_mysql -> param_bind [row ];
79
77
80
- switch (rows [row ]. kind ) {
78
+ switch (signature [row ]) {
81
79
case 's' :
82
80
param -> buffer_type = MYSQL_TYPE_STRING ;
83
81
param -> buffer = rows [row ].u .s ;
@@ -98,28 +96,24 @@ static bool db_stmt_bind_mysql(const struct db_stmt *stmt,
98
96
}
99
97
100
98
static bool db_stmt_step_mysql (const struct db_stmt * stmt ,
101
- const char * signature ,
102
99
va_list ap )
103
100
{
104
101
struct db_stmt_mysql * stmt_mysql = (struct db_stmt_mysql * )stmt ;
105
102
106
103
if (stmt_mysql -> must_execute_again ) {
107
104
stmt_mysql -> must_execute_again = false;
105
+ stmt_mysql -> results_are_bound = false;
108
106
if (mysql_stmt_execute (stmt_mysql -> stmt ))
109
107
return false;
110
108
}
111
109
112
- if (!stmt_mysql -> result_bind ) {
113
- if (* signature == '\0' )
114
- return false;
110
+ if (!stmt_mysql -> results_are_bound ) {
111
+ const char * signature = stmt -> result_signature ;
115
112
116
- stmt_mysql -> result_bind =
117
- calloc (strlen (signature ), sizeof (* stmt_mysql -> result_bind ));
118
- if (!stmt_mysql -> result_bind )
113
+ if (* signature == '\0' )
119
114
return false;
120
115
121
- free (stmt_mysql -> param_bind );
122
- stmt_mysql -> param_bind = NULL ;
116
+ stmt_mysql -> results_are_bound = true;
123
117
124
118
MYSQL_BIND * result = stmt_mysql -> result_bind ;
125
119
for (size_t r = 0 ; signature [r ]; r ++ ) {
@@ -148,9 +142,7 @@ static bool db_stmt_step_mysql(const struct db_stmt *stmt,
148
142
return mysql_stmt_fetch (stmt_mysql -> stmt ) == 0 ;
149
143
150
144
out :
151
- free (stmt_mysql -> result_bind );
152
- stmt_mysql -> result_bind = NULL ;
153
-
145
+ stmt_mysql -> results_are_bound = false;
154
146
return false;
155
147
}
156
148
@@ -159,16 +151,18 @@ static void db_stmt_finalize_mysql(struct db_stmt *stmt)
159
151
struct db_stmt_mysql * stmt_mysql = (struct db_stmt_mysql * )stmt ;
160
152
161
153
mysql_stmt_close (stmt_mysql -> stmt );
162
- free (stmt_mysql -> result_bind );
163
- free (stmt_mysql -> param_bind );
164
154
free (stmt_mysql );
165
155
}
166
156
167
157
static struct db_stmt *
168
- db_prepare_mysql (const struct db * db , const char * sql , const size_t sql_len )
158
+ db_prepare_mysql (const struct db * db ,
159
+ const char * sql ,
160
+ const char * param_signature ,
161
+ const char * result_signature )
169
162
{
170
163
const struct db_mysql * db_mysql = (const struct db_mysql * )db ;
171
- struct db_stmt_mysql * stmt_mysql = malloc (sizeof (* stmt_mysql ));
164
+ const size_t n_bounds = strlen (param_signature ) + strlen (result_signature );
165
+ struct db_stmt_mysql * stmt_mysql = malloc (sizeof (* stmt_mysql ) + n_bounds * sizeof (MYSQL_BIND ));
172
166
173
167
if (!stmt_mysql )
174
168
return NULL ;
@@ -177,15 +171,24 @@ db_prepare_mysql(const struct db *db, const char *sql, const size_t sql_len)
177
171
if (!stmt_mysql -> stmt )
178
172
goto out_free_stmt ;
179
173
180
- if (mysql_stmt_prepare (stmt_mysql -> stmt , sql , sql_len ))
174
+ if (mysql_stmt_prepare (stmt_mysql -> stmt , sql , strlen ( sql ) ))
181
175
goto out_close_stmt ;
182
176
177
+ assert (strlen (param_signature ) == mysql_stmt_param_count (stmt_mysql -> stmt ));
178
+ assert (strlen (result_signature ) == mysql_stmt_field_count (stmt_mysql -> stmt ));
179
+
183
180
stmt_mysql -> base .bind = db_stmt_bind_mysql ;
184
181
stmt_mysql -> base .step = db_stmt_step_mysql ;
185
182
stmt_mysql -> base .finalize = db_stmt_finalize_mysql ;
186
- stmt_mysql -> result_bind = NULL ;
187
- stmt_mysql -> param_bind = NULL ;
183
+ stmt_mysql -> param_bind = & stmt_mysql -> param_result_bind [ 0 ] ;
184
+ stmt_mysql -> result_bind = & stmt_mysql -> param_result_bind [ strlen ( param_signature )] ;
188
185
stmt_mysql -> must_execute_again = true;
186
+ stmt_mysql -> results_are_bound = false;
187
+
188
+ stmt_mysql -> base .param_signature = param_signature ;
189
+ stmt_mysql -> base .result_signature = result_signature ;
190
+
191
+ memset (stmt_mysql -> param_result_bind , 0 , n_bounds * sizeof (MYSQL_BIND ));
189
192
190
193
return (struct db_stmt * )stmt_mysql ;
191
194
@@ -252,26 +255,26 @@ struct db_stmt_sqlite {
252
255
};
253
256
254
257
static bool db_stmt_bind_sqlite (const struct db_stmt * stmt ,
255
- struct db_row * rows ,
256
- size_t n_rows )
258
+ struct db_row * rows )
257
259
{
258
260
const struct db_stmt_sqlite * stmt_sqlite =
259
261
(const struct db_stmt_sqlite * )stmt ;
262
+ const char * signature = stmt -> param_signature ;
260
263
261
264
sqlite3_reset (stmt_sqlite -> sqlite );
262
265
sqlite3_clear_bindings (stmt_sqlite -> sqlite );
263
266
264
- for (size_t row = 1 ; row <= n_rows ; row ++ ) {
265
- const struct db_row * r = & rows [row - 1 ];
267
+ for (size_t row = 0 ; signature [ row ] ; row ++ ) {
268
+ const struct db_row * r = & rows [row ];
266
269
int ret ;
267
270
268
- switch (r -> kind ) {
271
+ switch (signature [ row ] ) {
269
272
case 's' :
270
- ret = sqlite3_bind_text (stmt_sqlite -> sqlite , (int )row , r -> u .s , -1 ,
273
+ ret = sqlite3_bind_text (stmt_sqlite -> sqlite , (int )row + 1 , r -> u .s , -1 ,
271
274
NULL );
272
275
break ;
273
276
case 'i' :
274
- ret = sqlite3_bind_int (stmt_sqlite -> sqlite , (int )row , r -> u .i );
277
+ ret = sqlite3_bind_int (stmt_sqlite -> sqlite , (int )row + 1 , r -> u .i );
275
278
break ;
276
279
default :
277
280
return false;
@@ -285,11 +288,11 @@ static bool db_stmt_bind_sqlite(const struct db_stmt *stmt,
285
288
}
286
289
287
290
static bool db_stmt_step_sqlite (const struct db_stmt * stmt ,
288
- const char * signature ,
289
291
va_list ap )
290
292
{
291
293
const struct db_stmt_sqlite * stmt_sqlite =
292
294
(const struct db_stmt_sqlite * )stmt ;
295
+ const char * signature = stmt -> result_signature ;
293
296
294
297
if (sqlite3_step (stmt_sqlite -> sqlite ) != SQLITE_ROW )
295
298
return false;
@@ -326,15 +329,18 @@ static void db_stmt_finalize_sqlite(struct db_stmt *stmt)
326
329
}
327
330
328
331
static struct db_stmt *
329
- db_prepare_sqlite (const struct db * db , const char * sql , const size_t sql_len )
332
+ db_prepare_sqlite (const struct db * db ,
333
+ const char * sql ,
334
+ const char * param_signature ,
335
+ const char * result_signature )
330
336
{
331
337
const struct db_sqlite * db_sqlite = (const struct db_sqlite * )db ;
332
338
struct db_stmt_sqlite * stmt_sqlite = malloc (sizeof (* stmt_sqlite ));
333
339
334
340
if (!stmt_sqlite )
335
341
return NULL ;
336
342
337
- int ret = sqlite3_prepare_v2 (db_sqlite -> sqlite , sql , (int )sql_len ,
343
+ int ret = sqlite3_prepare_v2 (db_sqlite -> sqlite , sql , (int )strlen ( sql ) ,
338
344
& stmt_sqlite -> sqlite , NULL );
339
345
if (ret != SQLITE_OK ) {
340
346
free (stmt_sqlite );
@@ -345,6 +351,9 @@ db_prepare_sqlite(const struct db *db, const char *sql, const size_t sql_len)
345
351
stmt_sqlite -> base .step = db_stmt_step_sqlite ;
346
352
stmt_sqlite -> base .finalize = db_stmt_finalize_sqlite ;
347
353
354
+ stmt_sqlite -> base .param_signature = param_signature ;
355
+ stmt_sqlite -> base .result_signature = result_signature ;
356
+
348
357
return (struct db_stmt * )stmt_sqlite ;
349
358
}
350
359
@@ -384,20 +393,18 @@ db_connect_sqlite(const char *path, bool read_only, const char *pragmas[])
384
393
385
394
/* Generic */
386
395
387
- inline bool
388
- db_stmt_bind (const struct db_stmt * stmt , struct db_row * rows , size_t n_rows )
396
+ inline bool db_stmt_bind (const struct db_stmt * stmt , struct db_row * rows )
389
397
{
390
- return stmt -> bind (stmt , rows , n_rows );
398
+ return stmt -> bind (stmt , rows );
391
399
}
392
400
393
- inline bool
394
- db_stmt_step (const struct db_stmt * stmt , const char * signature , ...)
401
+ inline bool db_stmt_step (const struct db_stmt * stmt , ...)
395
402
{
396
403
va_list ap ;
397
404
bool ret ;
398
405
399
- va_start (ap , signature );
400
- ret = stmt -> step (stmt , signature , ap );
406
+ va_start (ap , stmt );
407
+ ret = stmt -> step (stmt , ap );
401
408
va_end (ap );
402
409
403
410
return ret ;
@@ -407,8 +414,10 @@ inline void db_stmt_finalize(struct db_stmt *stmt) { stmt->finalize(stmt); }
407
414
408
415
inline void db_disconnect (struct db * db ) { db -> disconnect (db ); }
409
416
410
- inline struct db_stmt *
411
- db_prepare_stmt (const struct db * db , const char * sql , const size_t sql_len )
417
+ inline struct db_stmt * db_prepare_stmt (const struct db * db ,
418
+ const char * sql ,
419
+ const char * param_signature ,
420
+ const char * result_signature )
412
421
{
413
- return db -> prepare (db , sql , sql_len );
422
+ return db -> prepare (db , sql , param_signature , result_signature );
414
423
}
0 commit comments