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.
26 #include "apr_strings.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
{
43 apr_dbd_transaction_t
*trans
;
45 apr_dbd_prepared_t
*prep
;
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
;
63 struct apr_dbd_results_t
{
67 apr_dbd_row_t
*next_row
;
74 struct apr_dbd_prepared_t
{
76 apr_dbd_prepared_t
*next
;
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
,
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;
92 apr_dbd_row_t
*row
= NULL
;
93 apr_dbd_row_t
*lastrow
= NULL
;
94 apr_dbd_column_t
*column
;
97 column_count
= sqlite3_column_count(stmt
);
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
;
109 ret
= sqlite3_step(stmt
);
110 if (ret
== SQLITE_BUSY
) {
111 if (retry_count
++ > MAX_RETRY_COUNT
) {
114 apr_dbd_mutex_unlock();
115 apr_sleep(MAX_RETRY_SLEEP
);
116 apr_dbd_mutex_lock();
118 } else if (ret
== SQLITE_ROW
) {
120 apr_dbd_column_t
*col
;
121 row
= apr_palloc(pool
, sizeof(apr_dbd_row_t
));
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
) {
143 hold
= (char *) sqlite3_column_text(stmt
, i
);
145 column
->value
= apr_pstrmemdup(pool
, hold
,
150 hold
= (char *) sqlite3_column_blob(stmt
, i
);
152 column
->value
= apr_pstrmemdup(pool
, hold
,
159 col
= row
->columns
[i
];
161 row
->rownum
= num_tuples
++;
163 (*results
)->tuples
= num_tuples
;
164 if ((*results
)->next_row
== 0) {
165 (*results
)->next_row
= row
;
168 lastrow
->next_row
= row
;
172 } while (ret
== SQLITE_ROW
|| ret
== SQLITE_BUSY
);
174 if (dbd_sqlite3_is_success(ret
)) {
180 static int dbd_sqlite3_select(apr_pool_t
*pool
, apr_dbd_t
*sql
,
181 apr_dbd_results_t
**results
, const char *query
,
184 sqlite3_stmt
*stmt
= NULL
;
185 const char *tail
= NULL
;
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
;
208 static const char *dbd_sqlite3_get_name(const apr_dbd_results_t
*res
, int n
)
210 if ((n
< 0) || (n
>= res
->sz
)) {
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
)
223 *rowp
= res
->next_row
;
226 res
->next_row
= (*rowp
)->next_row
;
229 if (rownum
> res
->tuples
) {
233 *rowp
= res
->next_row
;
234 for (; *rowp
!= 0; i
++, *rowp
= (*rowp
)->next_row
) {
244 static const char *dbd_sqlite3_get_entry(const apr_dbd_row_t
*row
, int n
)
246 apr_dbd_column_t
*column
;
248 if ((n
< 0) || (n
>= row
->columnCount
)) {
251 column
= row
->columns
[n
];
252 value
= column
->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
)) {
263 if (row
->columns
[n
]->type
== SQLITE_NULL
) {
268 case APR_DBD_TYPE_TINY
:
269 *(char*)data
= atoi(row
->columns
[n
]->value
);
271 case APR_DBD_TYPE_UTINY
:
272 *(unsigned char*)data
= atoi(row
->columns
[n
]->value
);
274 case APR_DBD_TYPE_SHORT
:
275 *(short*)data
= atoi(row
->columns
[n
]->value
);
277 case APR_DBD_TYPE_USHORT
:
278 *(unsigned short*)data
= atoi(row
->columns
[n
]->value
);
280 case APR_DBD_TYPE_INT
:
281 *(int*)data
= atoi(row
->columns
[n
]->value
);
283 case APR_DBD_TYPE_UINT
:
284 *(unsigned int*)data
= atoi(row
->columns
[n
]->value
);
286 case APR_DBD_TYPE_LONG
:
287 *(long*)data
= atol(row
->columns
[n
]->value
);
289 case APR_DBD_TYPE_ULONG
:
290 *(unsigned long*)data
= atol(row
->columns
[n
]->value
);
292 case APR_DBD_TYPE_LONGLONG
:
293 *(apr_int64_t
*)data
= apr_atoi64(row
->columns
[n
]->value
);
295 case APR_DBD_TYPE_ULONGLONG
:
296 *(apr_uint64_t
*)data
= apr_atoi64(row
->columns
[n
]->value
);
298 case APR_DBD_TYPE_FLOAT
:
299 *(float*)data
= atof(row
->columns
[n
]->value
);
301 case APR_DBD_TYPE_DOUBLE
:
302 *(double*)data
= atof(row
->columns
[n
]->value
);
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
;
313 case APR_DBD_TYPE_BLOB
:
314 case APR_DBD_TYPE_CLOB
:
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
);
325 case APR_DBD_TYPE_NULL
:
326 *(void**)data
= NULL
;
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
,
343 int ret
= -1, retry_count
= 0;
345 while(retry_count
++ <= MAX_RETRY_COUNT
) {
346 ret
= sqlite3_step(stmt
);
347 if (ret
!= SQLITE_BUSY
)
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
)) {
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();
377 ret
= sqlite3_prepare(sql
->conn
, query
, length
, &stmt
, &tail
);
378 if (ret
!= SQLITE_OK
) {
379 sqlite3_finalize(stmt
);
383 ret
= dbd_sqlite3_query_internal(sql
, stmt
, nrows
);
385 sqlite3_finalize(stmt
);
386 length
-= (tail
- query
);
388 } while (length
> 0);
390 apr_dbd_mutex_unlock();
392 if (TXN_NOTICE_ERRORS(sql
->trans
)) {
393 sql
->trans
->errnum
= ret
;
398 static apr_status_t
free_mem(void *data
)
404 static const char *dbd_sqlite3_escape(apr_pool_t
*pool
, const char *arg
,
407 char *ret
= sqlite3_mprintf("%q", arg
);
408 apr_pool_cleanup_register(pool
, ret
, free_mem
,
409 apr_pool_cleanup_null
);
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
)
419 const char *tail
= NULL
;
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
));
430 prep
->next
= sql
->prep
;
435 /* link new statement to the handle */
440 sqlite3_finalize(stmt
);
443 apr_dbd_mutex_unlock();
448 static void dbd_sqlite3_bind(apr_dbd_prepared_t
*statement
, const char **values
)
450 sqlite3_stmt
*stmt
= statement
->stmt
;
453 for (i
= 0, j
= 0; i
< statement
->nargs
; i
++, j
++) {
454 if (values
[j
] == NULL
) {
455 sqlite3_bind_null(stmt
, i
+ 1);
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 */
468 sqlite3_bind_blob(stmt
, i
+ 1, data
, size
, SQLITE_STATIC
);
472 sqlite3_bind_text(stmt
, i
+ 1, values
[j
],
473 strlen(values
[j
]), SQLITE_STATIC
);
482 static int dbd_sqlite3_pquery(apr_pool_t
*pool
, apr_dbd_t
*sql
,
483 int *nrows
, apr_dbd_prepared_t
*statement
,
486 sqlite3_stmt
*stmt
= statement
->stmt
;
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
);
504 apr_dbd_mutex_unlock();
506 if (TXN_NOTICE_ERRORS(sql
->trans
)) {
507 sql
->trans
->errnum
= 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
)
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
,
536 sqlite3_stmt
*stmt
= statement
->stmt
;
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
);
554 apr_dbd_mutex_unlock();
556 if (TXN_NOTICE_ERRORS(sql
->trans
)) {
557 sql
->trans
->errnum
= 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
,
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
,
586 sqlite3_stmt
*stmt
= statement
->stmt
;
590 for (i
= 0, j
= 0; i
< statement
->nargs
; i
++, j
++) {
591 type
= (values
[j
] == NULL
? APR_DBD_TYPE_NULL
: statement
->types
[i
]);
594 case APR_DBD_TYPE_TINY
:
595 sqlite3_bind_int(stmt
, i
+ 1, *(char*)values
[j
]);
597 case APR_DBD_TYPE_UTINY
:
598 sqlite3_bind_int(stmt
, i
+ 1, *(unsigned char*)values
[j
]);
600 case APR_DBD_TYPE_SHORT
:
601 sqlite3_bind_int(stmt
, i
+ 1, *(short*)values
[j
]);
603 case APR_DBD_TYPE_USHORT
:
604 sqlite3_bind_int(stmt
, i
+ 1, *(unsigned short*)values
[j
]);
606 case APR_DBD_TYPE_INT
:
607 sqlite3_bind_int(stmt
, i
+ 1, *(int*)values
[j
]);
609 case APR_DBD_TYPE_UINT
:
610 sqlite3_bind_int(stmt
, i
+ 1, *(unsigned int*)values
[j
]);
612 case APR_DBD_TYPE_LONG
:
613 sqlite3_bind_int64(stmt
, i
+ 1, *(long*)values
[j
]);
615 case APR_DBD_TYPE_ULONG
:
616 sqlite3_bind_int64(stmt
, i
+ 1, *(unsigned long*)values
[j
]);
618 case APR_DBD_TYPE_LONGLONG
:
619 sqlite3_bind_int64(stmt
, i
+ 1, *(apr_int64_t
*)values
[j
]);
621 case APR_DBD_TYPE_ULONGLONG
:
622 sqlite3_bind_int64(stmt
, i
+ 1, *(apr_uint64_t
*)values
[j
]);
624 case APR_DBD_TYPE_FLOAT
:
625 sqlite3_bind_double(stmt
, i
+ 1, *(float*)values
[j
]);
627 case APR_DBD_TYPE_DOUBLE
:
628 sqlite3_bind_double(stmt
, i
+ 1, *(double*)values
[j
]);
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
]),
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 */
652 case APR_DBD_TYPE_NULL
:
654 sqlite3_bind_null(stmt
, i
+ 1);
662 static int dbd_sqlite3_pbquery(apr_pool_t
* pool
, apr_dbd_t
* sql
,
663 int *nrows
, apr_dbd_prepared_t
* statement
,
666 sqlite3_stmt
*stmt
= statement
->stmt
;
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
);
684 apr_dbd_mutex_unlock();
686 if (TXN_NOTICE_ERRORS(sql
->trans
)) {
687 sql
->trans
->errnum
= ret
;
692 static int dbd_sqlite3_pvbquery(apr_pool_t
* pool
, apr_dbd_t
* sql
,
693 int *nrows
, apr_dbd_prepared_t
* statement
,
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
;
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
);
735 apr_dbd_mutex_unlock();
737 if (TXN_NOTICE_ERRORS(sql
->trans
)) {
738 sql
->trans
->errnum
= 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
,
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
,
766 apr_dbd_transaction_t
**trans
)
771 ret
= dbd_sqlite3_query(handle
, &nrows
, "BEGIN IMMEDIATE");
773 *trans
= apr_pcalloc(pool
, sizeof(apr_dbd_transaction_t
));
774 (*trans
)->handle
= handle
;
775 handle
->trans
= *trans
;
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 */
787 /* rollback on error or explicit rollback request */
788 if (trans
->errnum
|| TXN_DO_ROLLBACK(trans
)) {
790 ret
= dbd_sqlite3_query(trans
->handle
, &nrows
, "ROLLBACK");
792 ret
= dbd_sqlite3_query(trans
->handle
, &nrows
, "COMMIT");
794 trans
->handle
->trans
= NULL
;
800 static int dbd_sqlite3_transaction_mode_get(apr_dbd_transaction_t
*trans
)
803 return APR_DBD_TRANSACTION_COMMIT
;
808 static int dbd_sqlite3_transaction_mode_set(apr_dbd_transaction_t
*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
;
824 sqlres
= sqlite3_open(params
, &conn
);
825 if (sqlres
!= SQLITE_OK
) {
829 /* should we register rand or power functions to the sqlite VM? */
830 sql
= apr_pcalloc(pool
, sizeof(*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 */
844 sqlite3_finalize(prep
->stmt
);
848 sqlite3_close(handle
->conn
);
852 static apr_status_t
dbd_sqlite3_check_conn(apr_pool_t
*pool
,
855 return (handle
->conn
!= NULL
) ? APR_SUCCESS
: APR_EGENERAL
;
858 static int dbd_sqlite3_select_db(apr_pool_t
*pool
, apr_dbd_t
*handle
,
864 static void *dbd_sqlite3_native(apr_dbd_t
*handle
)
869 static int dbd_sqlite3_num_cols(apr_dbd_results_t
*res
)
874 static int dbd_sqlite3_num_tuples(apr_dbd_results_t
*res
)
879 APU_DECLARE_DATA
const apr_dbd_driver_t apr_dbd_sqlite3_driver
= {
884 dbd_sqlite3_check_conn
,
886 dbd_sqlite3_select_db
,
887 dbd_sqlite3_start_transaction
,
888 dbd_sqlite3_end_transaction
,
891 dbd_sqlite3_num_cols
,
892 dbd_sqlite3_num_tuples
,
894 dbd_sqlite3_get_entry
,
899 dbd_sqlite3_pvselect
,
902 dbd_sqlite3_get_name
,
903 dbd_sqlite3_transaction_mode_get
,
904 dbd_sqlite3_transaction_mode_set
,
906 dbd_sqlite3_pvbquery
,
907 dbd_sqlite3_pvbselect
,
909 dbd_sqlite3_pbselect
,
910 dbd_sqlite3_datum_get