Unify parsing of prepared statements in DBD
[apr-util.git] / dbd / apr_dbd_sqlite3.c
bloba5543db3a3f49705f553443f72ea3ea919d7471c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "apu.h"
19 #if APU_HAVE_SQLITE3
21 #include <ctype.h>
22 #include <stdlib.h>
24 #include <sqlite3.h>
26 #include "apr_strings.h"
27 #include "apr_time.h"
28 #include "apr_buckets.h"
30 #include "apr_dbd_internal.h"
32 #define MAX_RETRY_COUNT 15
33 #define MAX_RETRY_SLEEP 100000
35 struct apr_dbd_transaction_t {
36 int mode;
37 int errnum;
38 apr_dbd_t *handle;
41 struct apr_dbd_t {
42 sqlite3 *conn;
43 apr_dbd_transaction_t *trans;
44 apr_pool_t *pool;
45 apr_dbd_prepared_t *prep;
48 typedef struct {
49 char *name;
50 char *value;
51 int size;
52 int type;
53 } apr_dbd_column_t;
55 struct apr_dbd_row_t {
56 apr_dbd_results_t *res;
57 apr_dbd_column_t **columns;
58 apr_dbd_row_t *next_row;
59 int columnCount;
60 int rownum;
63 struct apr_dbd_results_t {
64 int random;
65 sqlite3 *handle;
66 sqlite3_stmt *stmt;
67 apr_dbd_row_t *next_row;
68 size_t sz;
69 int tuples;
70 char **col_names;
71 apr_pool_t *pool;
74 struct apr_dbd_prepared_t {
75 sqlite3_stmt *stmt;
76 apr_dbd_prepared_t *next;
77 int nargs;
78 int nvals;
79 apr_dbd_type_e *types;
82 #define dbd_sqlite3_is_success(x) (((x) == SQLITE_DONE) || ((x) == SQLITE_OK))
84 static int dbd_sqlite3_select_internal(apr_pool_t *pool,
85 apr_dbd_t *sql,
86 apr_dbd_results_t **results,
87 sqlite3_stmt *stmt, int seek)
89 int i, ret, retry_count = 0, column_count;
90 size_t num_tuples = 0;
91 int increment = 0;
92 apr_dbd_row_t *row = NULL;
93 apr_dbd_row_t *lastrow = NULL;
94 apr_dbd_column_t *column;
95 char *hold = NULL;
97 column_count = sqlite3_column_count(stmt);
98 if (!*results) {
99 *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
101 (*results)->stmt = stmt;
102 (*results)->sz = column_count;
103 (*results)->random = seek;
104 (*results)->next_row = 0;
105 (*results)->tuples = 0;
106 (*results)->col_names = apr_pcalloc(pool, column_count * sizeof(char *));
107 (*results)->pool = pool;
108 do {
109 ret = sqlite3_step(stmt);
110 if (ret == SQLITE_BUSY) {
111 if (retry_count++ > MAX_RETRY_COUNT) {
112 ret = SQLITE_ERROR;
113 } else {
114 apr_dbd_mutex_unlock();
115 apr_sleep(MAX_RETRY_SLEEP);
116 apr_dbd_mutex_lock();
118 } else if (ret == SQLITE_ROW) {
119 int length;
120 apr_dbd_column_t *col;
121 row = apr_palloc(pool, sizeof(apr_dbd_row_t));
122 row->res = *results;
123 increment = sizeof(apr_dbd_column_t *);
124 length = increment * (*results)->sz;
125 row->columns = apr_palloc(pool, length);
126 row->columnCount = column_count;
127 for (i = 0; i < (*results)->sz; i++) {
128 column = apr_palloc(pool, sizeof(apr_dbd_column_t));
129 row->columns[i] = column;
130 /* copy column name once only */
131 if ((*results)->col_names[i] == NULL) {
132 (*results)->col_names[i] =
133 apr_pstrdup(pool, sqlite3_column_name(stmt, i));
135 column->name = (*results)->col_names[i];
136 column->size = sqlite3_column_bytes(stmt, i);
137 column->type = sqlite3_column_type(stmt, i);
138 column->value = NULL;
139 switch (column->type) {
140 case SQLITE_FLOAT:
141 case SQLITE_INTEGER:
142 case SQLITE_TEXT:
143 hold = (char *) sqlite3_column_text(stmt, i);
144 if (hold) {
145 column->value = apr_pstrmemdup(pool, hold,
146 column->size);
148 break;
149 case SQLITE_BLOB:
150 hold = (char *) sqlite3_column_blob(stmt, i);
151 if (hold) {
152 column->value = apr_pstrmemdup(pool, hold,
153 column->size);
155 break;
156 case SQLITE_NULL:
157 break;
159 col = row->columns[i];
161 row->rownum = num_tuples++;
162 row->next_row = 0;
163 (*results)->tuples = num_tuples;
164 if ((*results)->next_row == 0) {
165 (*results)->next_row = row;
167 if (lastrow != 0) {
168 lastrow->next_row = row;
170 lastrow = row;
172 } while (ret == SQLITE_ROW || ret == SQLITE_BUSY);
174 if (dbd_sqlite3_is_success(ret)) {
175 ret = 0;
177 return ret;
180 static int dbd_sqlite3_select(apr_pool_t *pool, apr_dbd_t *sql,
181 apr_dbd_results_t **results, const char *query,
182 int seek)
184 sqlite3_stmt *stmt = NULL;
185 const char *tail = NULL;
186 int ret;
188 if (sql->trans && sql->trans->errnum) {
189 return sql->trans->errnum;
192 apr_dbd_mutex_lock();
194 ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail);
195 if (dbd_sqlite3_is_success(ret)) {
196 ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
198 sqlite3_finalize(stmt);
200 apr_dbd_mutex_unlock();
202 if (TXN_NOTICE_ERRORS(sql->trans)) {
203 sql->trans->errnum = ret;
205 return ret;
208 static const char *dbd_sqlite3_get_name(const apr_dbd_results_t *res, int n)
210 if ((n < 0) || (n >= res->sz)) {
211 return NULL;
214 return res->col_names[n];
217 static int dbd_sqlite3_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
218 apr_dbd_row_t **rowp, int rownum)
220 int i = 0;
222 if (rownum == -1) {
223 *rowp = res->next_row;
224 if (*rowp == 0)
225 return -1;
226 res->next_row = (*rowp)->next_row;
227 return 0;
229 if (rownum > res->tuples) {
230 return -1;
232 rownum--;
233 *rowp = res->next_row;
234 for (; *rowp != 0; i++, *rowp = (*rowp)->next_row) {
235 if (i == rownum) {
236 return 0;
240 return -1;
244 static const char *dbd_sqlite3_get_entry(const apr_dbd_row_t *row, int n)
246 apr_dbd_column_t *column;
247 const char *value;
248 if ((n < 0) || (n >= row->columnCount)) {
249 return NULL;
251 column = row->columns[n];
252 value = column->value;
253 return value;
256 static apr_status_t dbd_sqlite3_datum_get(const apr_dbd_row_t *row, int n,
257 apr_dbd_type_e type, void *data)
259 if ((n < 0) || (n >= row->res->sz)) {
260 return APR_EGENERAL;
263 if (row->columns[n]->type == SQLITE_NULL) {
264 return APR_ENOENT;
267 switch (type) {
268 case APR_DBD_TYPE_TINY:
269 *(char*)data = atoi(row->columns[n]->value);
270 break;
271 case APR_DBD_TYPE_UTINY:
272 *(unsigned char*)data = atoi(row->columns[n]->value);
273 break;
274 case APR_DBD_TYPE_SHORT:
275 *(short*)data = atoi(row->columns[n]->value);
276 break;
277 case APR_DBD_TYPE_USHORT:
278 *(unsigned short*)data = atoi(row->columns[n]->value);
279 break;
280 case APR_DBD_TYPE_INT:
281 *(int*)data = atoi(row->columns[n]->value);
282 break;
283 case APR_DBD_TYPE_UINT:
284 *(unsigned int*)data = atoi(row->columns[n]->value);
285 break;
286 case APR_DBD_TYPE_LONG:
287 *(long*)data = atol(row->columns[n]->value);
288 break;
289 case APR_DBD_TYPE_ULONG:
290 *(unsigned long*)data = atol(row->columns[n]->value);
291 break;
292 case APR_DBD_TYPE_LONGLONG:
293 *(apr_int64_t*)data = apr_atoi64(row->columns[n]->value);
294 break;
295 case APR_DBD_TYPE_ULONGLONG:
296 *(apr_uint64_t*)data = apr_atoi64(row->columns[n]->value);
297 break;
298 case APR_DBD_TYPE_FLOAT:
299 *(float*)data = atof(row->columns[n]->value);
300 break;
301 case APR_DBD_TYPE_DOUBLE:
302 *(double*)data = atof(row->columns[n]->value);
303 break;
304 case APR_DBD_TYPE_STRING:
305 case APR_DBD_TYPE_TEXT:
306 case APR_DBD_TYPE_TIME:
307 case APR_DBD_TYPE_DATE:
308 case APR_DBD_TYPE_DATETIME:
309 case APR_DBD_TYPE_TIMESTAMP:
310 case APR_DBD_TYPE_ZTIMESTAMP:
311 *(char**)data = row->columns[n]->value;
312 break;
313 case APR_DBD_TYPE_BLOB:
314 case APR_DBD_TYPE_CLOB:
316 apr_bucket *e;
317 apr_bucket_brigade *b = (apr_bucket_brigade*)data;
319 e = apr_bucket_pool_create(row->columns[n]->value,
320 row->columns[n]->size,
321 row->res->pool, b->bucket_alloc);
322 APR_BRIGADE_INSERT_TAIL(b, e);
324 break;
325 case APR_DBD_TYPE_NULL:
326 *(void**)data = NULL;
327 break;
328 default:
329 return APR_EGENERAL;
332 return APR_SUCCESS;
335 static const char *dbd_sqlite3_error(apr_dbd_t *sql, int n)
337 return sqlite3_errmsg(sql->conn);
340 static int dbd_sqlite3_query_internal(apr_dbd_t *sql, sqlite3_stmt *stmt,
341 int *nrows)
343 int ret = -1, retry_count = 0;
345 while(retry_count++ <= MAX_RETRY_COUNT) {
346 ret = sqlite3_step(stmt);
347 if (ret != SQLITE_BUSY)
348 break;
350 apr_dbd_mutex_unlock();
351 apr_sleep(MAX_RETRY_SLEEP);
352 apr_dbd_mutex_lock();
355 *nrows = sqlite3_changes(sql->conn);
357 if (dbd_sqlite3_is_success(ret)) {
358 ret = 0;
360 return ret;
363 static int dbd_sqlite3_query(apr_dbd_t *sql, int *nrows, const char *query)
365 sqlite3_stmt *stmt = NULL;
366 const char *tail = NULL;
367 int ret = -1, length = 0;
369 if (sql->trans && sql->trans->errnum) {
370 return sql->trans->errnum;
373 length = strlen(query);
374 apr_dbd_mutex_lock();
376 do {
377 ret = sqlite3_prepare(sql->conn, query, length, &stmt, &tail);
378 if (ret != SQLITE_OK) {
379 sqlite3_finalize(stmt);
380 break;
383 ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
385 sqlite3_finalize(stmt);
386 length -= (tail - query);
387 query = tail;
388 } while (length > 0);
390 apr_dbd_mutex_unlock();
392 if (TXN_NOTICE_ERRORS(sql->trans)) {
393 sql->trans->errnum = ret;
395 return ret;
398 static apr_status_t free_mem(void *data)
400 sqlite3_free(data);
401 return APR_SUCCESS;
404 static const char *dbd_sqlite3_escape(apr_pool_t *pool, const char *arg,
405 apr_dbd_t *sql)
407 char *ret = sqlite3_mprintf("%q", arg);
408 apr_pool_cleanup_register(pool, ret, free_mem,
409 apr_pool_cleanup_null);
410 return ret;
413 static int dbd_sqlite3_prepare(apr_pool_t *pool, apr_dbd_t *sql,
414 const char *query, const char *label,
415 int nargs, int nvals, apr_dbd_type_e *types,
416 apr_dbd_prepared_t **statement)
418 sqlite3_stmt *stmt;
419 const char *tail = NULL;
420 int ret;
422 apr_dbd_mutex_lock();
424 ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail);
425 if (ret == SQLITE_OK) {
426 apr_dbd_prepared_t *prep;
428 prep = apr_pcalloc(sql->pool, sizeof(*prep));
429 prep->stmt = stmt;
430 prep->next = sql->prep;
431 prep->nargs = nargs;
432 prep->nvals = nvals;
433 prep->types = types;
435 /* link new statement to the handle */
436 sql->prep = prep;
438 *statement = prep;
439 } else {
440 sqlite3_finalize(stmt);
443 apr_dbd_mutex_unlock();
445 return ret;
448 static void dbd_sqlite3_bind(apr_dbd_prepared_t *statement, const char **values)
450 sqlite3_stmt *stmt = statement->stmt;
451 int i, j;
453 for (i = 0, j = 0; i < statement->nargs; i++, j++) {
454 if (values[j] == NULL) {
455 sqlite3_bind_null(stmt, i + 1);
457 else {
458 switch (statement->types[i]) {
459 case APR_DBD_TYPE_BLOB:
460 case APR_DBD_TYPE_CLOB:
462 char *data = (char *)values[j];
463 int size = atoi((char*)values[++j]);
465 /* skip table and column */
466 j += 2;
468 sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC);
470 break;
471 default:
472 sqlite3_bind_text(stmt, i + 1, values[j],
473 strlen(values[j]), SQLITE_STATIC);
474 break;
479 return;
482 static int dbd_sqlite3_pquery(apr_pool_t *pool, apr_dbd_t *sql,
483 int *nrows, apr_dbd_prepared_t *statement,
484 const char **values)
486 sqlite3_stmt *stmt = statement->stmt;
487 int ret = -1;
489 if (sql->trans && sql->trans->errnum) {
490 return sql->trans->errnum;
493 apr_dbd_mutex_lock();
495 ret = sqlite3_reset(stmt);
496 if (ret == SQLITE_OK) {
497 dbd_sqlite3_bind(statement, values);
499 ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
501 sqlite3_reset(stmt);
504 apr_dbd_mutex_unlock();
506 if (TXN_NOTICE_ERRORS(sql->trans)) {
507 sql->trans->errnum = ret;
509 return ret;
512 static int dbd_sqlite3_pvquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
513 apr_dbd_prepared_t *statement, va_list args)
515 const char **values;
516 int i;
518 if (sql->trans && sql->trans->errnum) {
519 return sql->trans->errnum;
522 values = apr_palloc(pool, sizeof(*values) * statement->nvals);
524 for (i = 0; i < statement->nvals; i++) {
525 values[i] = va_arg(args, const char*);
528 return dbd_sqlite3_pquery(pool, sql, nrows, statement, values);
531 static int dbd_sqlite3_pselect(apr_pool_t *pool, apr_dbd_t *sql,
532 apr_dbd_results_t **results,
533 apr_dbd_prepared_t *statement, int seek,
534 const char **values)
536 sqlite3_stmt *stmt = statement->stmt;
537 int ret;
539 if (sql->trans && sql->trans->errnum) {
540 return sql->trans->errnum;
543 apr_dbd_mutex_lock();
545 ret = sqlite3_reset(stmt);
546 if (ret == SQLITE_OK) {
547 dbd_sqlite3_bind(statement, values);
549 ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
551 sqlite3_reset(stmt);
554 apr_dbd_mutex_unlock();
556 if (TXN_NOTICE_ERRORS(sql->trans)) {
557 sql->trans->errnum = ret;
559 return ret;
562 static int dbd_sqlite3_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
563 apr_dbd_results_t **results,
564 apr_dbd_prepared_t *statement, int seek,
565 va_list args)
567 const char **values;
568 int i;
570 if (sql->trans && sql->trans->errnum) {
571 return sql->trans->errnum;
574 values = apr_palloc(pool, sizeof(*values) * statement->nvals);
576 for (i = 0; i < statement->nvals; i++) {
577 values[i] = va_arg(args, const char*);
580 return dbd_sqlite3_pselect(pool, sql, results, statement, seek, values);
583 static void dbd_sqlite3_bbind(apr_dbd_prepared_t * statement,
584 const void **values)
586 sqlite3_stmt *stmt = statement->stmt;
587 int i, j;
588 apr_dbd_type_e type;
590 for (i = 0, j = 0; i < statement->nargs; i++, j++) {
591 type = (values[j] == NULL ? APR_DBD_TYPE_NULL : statement->types[i]);
593 switch (type) {
594 case APR_DBD_TYPE_TINY:
595 sqlite3_bind_int(stmt, i + 1, *(char*)values[j]);
596 break;
597 case APR_DBD_TYPE_UTINY:
598 sqlite3_bind_int(stmt, i + 1, *(unsigned char*)values[j]);
599 break;
600 case APR_DBD_TYPE_SHORT:
601 sqlite3_bind_int(stmt, i + 1, *(short*)values[j]);
602 break;
603 case APR_DBD_TYPE_USHORT:
604 sqlite3_bind_int(stmt, i + 1, *(unsigned short*)values[j]);
605 break;
606 case APR_DBD_TYPE_INT:
607 sqlite3_bind_int(stmt, i + 1, *(int*)values[j]);
608 break;
609 case APR_DBD_TYPE_UINT:
610 sqlite3_bind_int(stmt, i + 1, *(unsigned int*)values[j]);
611 break;
612 case APR_DBD_TYPE_LONG:
613 sqlite3_bind_int64(stmt, i + 1, *(long*)values[j]);
614 break;
615 case APR_DBD_TYPE_ULONG:
616 sqlite3_bind_int64(stmt, i + 1, *(unsigned long*)values[j]);
617 break;
618 case APR_DBD_TYPE_LONGLONG:
619 sqlite3_bind_int64(stmt, i + 1, *(apr_int64_t*)values[j]);
620 break;
621 case APR_DBD_TYPE_ULONGLONG:
622 sqlite3_bind_int64(stmt, i + 1, *(apr_uint64_t*)values[j]);
623 break;
624 case APR_DBD_TYPE_FLOAT:
625 sqlite3_bind_double(stmt, i + 1, *(float*)values[j]);
626 break;
627 case APR_DBD_TYPE_DOUBLE:
628 sqlite3_bind_double(stmt, i + 1, *(double*)values[j]);
629 break;
630 case APR_DBD_TYPE_STRING:
631 case APR_DBD_TYPE_TEXT:
632 case APR_DBD_TYPE_TIME:
633 case APR_DBD_TYPE_DATE:
634 case APR_DBD_TYPE_DATETIME:
635 case APR_DBD_TYPE_TIMESTAMP:
636 case APR_DBD_TYPE_ZTIMESTAMP:
637 sqlite3_bind_text(stmt, i + 1, values[j], strlen(values[j]),
638 SQLITE_STATIC);
639 break;
640 case APR_DBD_TYPE_BLOB:
641 case APR_DBD_TYPE_CLOB:
643 char *data = (char*)values[j];
644 apr_size_t size = *(apr_size_t*)values[++j];
646 sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC);
648 /* skip table and column */
649 j += 2;
651 break;
652 case APR_DBD_TYPE_NULL:
653 default:
654 sqlite3_bind_null(stmt, i + 1);
655 break;
659 return;
662 static int dbd_sqlite3_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
663 int *nrows, apr_dbd_prepared_t * statement,
664 const void **values)
666 sqlite3_stmt *stmt = statement->stmt;
667 int ret = -1;
669 if (sql->trans && sql->trans->errnum) {
670 return sql->trans->errnum;
673 apr_dbd_mutex_lock();
675 ret = sqlite3_reset(stmt);
676 if (ret == SQLITE_OK) {
677 dbd_sqlite3_bbind(statement, values);
679 ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
681 sqlite3_reset(stmt);
684 apr_dbd_mutex_unlock();
686 if (TXN_NOTICE_ERRORS(sql->trans)) {
687 sql->trans->errnum = ret;
689 return ret;
692 static int dbd_sqlite3_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
693 int *nrows, apr_dbd_prepared_t * statement,
694 va_list args)
696 const void **values;
697 int i;
699 if (sql->trans && sql->trans->errnum) {
700 return sql->trans->errnum;
703 values = apr_palloc(pool, sizeof(*values) * statement->nvals);
705 for (i = 0; i < statement->nvals; i++) {
706 values[i] = va_arg(args, const void*);
709 return dbd_sqlite3_pbquery(pool, sql, nrows, statement, values);
712 static int dbd_sqlite3_pbselect(apr_pool_t * pool, apr_dbd_t * sql,
713 apr_dbd_results_t ** results,
714 apr_dbd_prepared_t * statement,
715 int seek, const void **values)
717 sqlite3_stmt *stmt = statement->stmt;
718 int ret;
720 if (sql->trans && sql->trans->errnum) {
721 return sql->trans->errnum;
724 apr_dbd_mutex_lock();
726 ret = sqlite3_reset(stmt);
727 if (ret == SQLITE_OK) {
728 dbd_sqlite3_bbind(statement, values);
730 ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
732 sqlite3_reset(stmt);
735 apr_dbd_mutex_unlock();
737 if (TXN_NOTICE_ERRORS(sql->trans)) {
738 sql->trans->errnum = ret;
740 return ret;
743 static int dbd_sqlite3_pvbselect(apr_pool_t * pool, apr_dbd_t * sql,
744 apr_dbd_results_t ** results,
745 apr_dbd_prepared_t * statement, int seek,
746 va_list args)
748 const void **values;
749 int i;
751 if (sql->trans && sql->trans->errnum) {
752 return sql->trans->errnum;
755 values = apr_palloc(pool, sizeof(*values) * statement->nvals);
757 for (i = 0; i < statement->nvals; i++) {
758 values[i] = va_arg(args, const void*);
761 return dbd_sqlite3_pbselect(pool, sql, results, statement, seek, values);
764 static int dbd_sqlite3_start_transaction(apr_pool_t *pool,
765 apr_dbd_t *handle,
766 apr_dbd_transaction_t **trans)
768 int ret = 0;
769 int nrows = 0;
771 ret = dbd_sqlite3_query(handle, &nrows, "BEGIN IMMEDIATE");
772 if (!*trans) {
773 *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
774 (*trans)->handle = handle;
775 handle->trans = *trans;
778 return ret;
781 static int dbd_sqlite3_end_transaction(apr_dbd_transaction_t *trans)
783 int ret = -1; /* ending transaction that was never started is an error */
784 int nrows = 0;
786 if (trans) {
787 /* rollback on error or explicit rollback request */
788 if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
789 trans->errnum = 0;
790 ret = dbd_sqlite3_query(trans->handle, &nrows, "ROLLBACK");
791 } else {
792 ret = dbd_sqlite3_query(trans->handle, &nrows, "COMMIT");
794 trans->handle->trans = NULL;
797 return ret;
800 static int dbd_sqlite3_transaction_mode_get(apr_dbd_transaction_t *trans)
802 if (!trans)
803 return APR_DBD_TRANSACTION_COMMIT;
805 return trans->mode;
808 static int dbd_sqlite3_transaction_mode_set(apr_dbd_transaction_t *trans,
809 int mode)
811 if (!trans)
812 return APR_DBD_TRANSACTION_COMMIT;
814 return trans->mode = (mode & TXN_MODE_BITS);
817 static apr_dbd_t *dbd_sqlite3_open(apr_pool_t *pool, const char *params)
819 apr_dbd_t *sql = NULL;
820 sqlite3 *conn = NULL;
821 int sqlres;
822 if (!params)
823 return NULL;
824 sqlres = sqlite3_open(params, &conn);
825 if (sqlres != SQLITE_OK) {
826 sqlite3_close(conn);
827 return NULL;
829 /* should we register rand or power functions to the sqlite VM? */
830 sql = apr_pcalloc(pool, sizeof(*sql));
831 sql->conn = conn;
832 sql->pool = pool;
833 sql->trans = NULL;
835 return sql;
838 static apr_status_t dbd_sqlite3_close(apr_dbd_t *handle)
840 apr_dbd_prepared_t *prep = handle->prep;
842 /* finalize all prepared statements, or we'll get SQLITE_BUSY on close */
843 while (prep) {
844 sqlite3_finalize(prep->stmt);
845 prep = prep->next;
848 sqlite3_close(handle->conn);
849 return APR_SUCCESS;
852 static apr_status_t dbd_sqlite3_check_conn(apr_pool_t *pool,
853 apr_dbd_t *handle)
855 return (handle->conn != NULL) ? APR_SUCCESS : APR_EGENERAL;
858 static int dbd_sqlite3_select_db(apr_pool_t *pool, apr_dbd_t *handle,
859 const char *name)
861 return APR_ENOTIMPL;
864 static void *dbd_sqlite3_native(apr_dbd_t *handle)
866 return handle->conn;
869 static int dbd_sqlite3_num_cols(apr_dbd_results_t *res)
871 return res->sz;
874 static int dbd_sqlite3_num_tuples(apr_dbd_results_t *res)
876 return res->tuples;
879 APU_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite3_driver = {
880 "sqlite3",
881 NULL,
882 dbd_sqlite3_native,
883 dbd_sqlite3_open,
884 dbd_sqlite3_check_conn,
885 dbd_sqlite3_close,
886 dbd_sqlite3_select_db,
887 dbd_sqlite3_start_transaction,
888 dbd_sqlite3_end_transaction,
889 dbd_sqlite3_query,
890 dbd_sqlite3_select,
891 dbd_sqlite3_num_cols,
892 dbd_sqlite3_num_tuples,
893 dbd_sqlite3_get_row,
894 dbd_sqlite3_get_entry,
895 dbd_sqlite3_error,
896 dbd_sqlite3_escape,
897 dbd_sqlite3_prepare,
898 dbd_sqlite3_pvquery,
899 dbd_sqlite3_pvselect,
900 dbd_sqlite3_pquery,
901 dbd_sqlite3_pselect,
902 dbd_sqlite3_get_name,
903 dbd_sqlite3_transaction_mode_get,
904 dbd_sqlite3_transaction_mode_set,
905 "?",
906 dbd_sqlite3_pvbquery,
907 dbd_sqlite3_pvbselect,
908 dbd_sqlite3_pbquery,
909 dbd_sqlite3_pbselect,
910 dbd_sqlite3_datum_get
912 #endif