Use of pre_cleanups is not the default for reslists.
[apr-util.git] / dbd / apr_dbd_sqlite2.c
blob132ccc4c65ab92cfe4635e82a11a4a66ffc2b38f
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_SQLITE2
21 #include <ctype.h>
22 #include <stdlib.h>
24 #include <sqlite.h>
26 #include "apr_strings.h"
27 #include "apr_time.h"
28 #include "apr_buckets.h"
30 #include "apr_dbd_internal.h"
32 struct apr_dbd_transaction_t {
33 int mode;
34 int errnum;
35 apr_dbd_t *handle;
38 struct apr_dbd_t {
39 sqlite *conn;
40 char *errmsg;
41 apr_dbd_transaction_t *trans;
44 struct apr_dbd_results_t {
45 int random;
46 sqlite *handle;
47 char **res;
48 size_t ntuples;
49 size_t sz;
50 size_t index;
51 apr_pool_t *pool;
54 struct apr_dbd_row_t {
55 int n;
56 char **data;
57 apr_dbd_results_t *res;
60 struct apr_dbd_prepared_t {
61 const char *name;
62 int prepared;
65 #define FREE_ERROR_MSG(dbd) \
66 do { \
67 if(dbd && dbd->errmsg) { \
68 free(dbd->errmsg); \
69 dbd->errmsg = NULL; \
70 } \
71 } while(0);
73 static apr_status_t free_table(void *data)
75 sqlite_free_table(data);
76 return APR_SUCCESS;
79 static int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql,
80 apr_dbd_results_t ** results, const char *query,
81 int seek)
83 char **result;
84 int ret = 0;
85 int tuples = 0;
86 int fields = 0;
88 if (sql->trans && sql->trans->errnum) {
89 return sql->trans->errnum;
92 FREE_ERROR_MSG(sql);
94 ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
95 &sql->errmsg);
97 if (ret == SQLITE_OK) {
98 if (!*results) {
99 *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
102 (*results)->res = result;
103 (*results)->ntuples = tuples;
104 (*results)->sz = fields;
105 (*results)->random = seek;
106 (*results)->pool = pool;
108 if (tuples > 0)
109 apr_pool_cleanup_register(pool, result, free_table,
110 apr_pool_cleanup_null);
112 ret = 0;
114 else {
115 if (TXN_NOTICE_ERRORS(sql->trans)) {
116 sql->trans->errnum = ret;
120 return ret;
123 static const char *dbd_sqlite_get_name(const apr_dbd_results_t *res, int n)
125 if ((n < 0) || (n >= res->sz)) {
126 return NULL;
129 return res->res[n];
132 static int dbd_sqlite_get_row(apr_pool_t * pool, apr_dbd_results_t * res,
133 apr_dbd_row_t ** rowp, int rownum)
135 apr_dbd_row_t *row = *rowp;
136 int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
138 if (row == NULL) {
139 row = apr_palloc(pool, sizeof(apr_dbd_row_t));
140 *rowp = row;
141 row->res = res;
142 row->n = sequential ? 0 : rownum - 1;
144 else {
145 if (sequential) {
146 ++row->n;
148 else {
149 row->n = rownum - 1;
153 if (row->n >= res->ntuples) {
154 *rowp = NULL;
155 apr_pool_cleanup_run(pool, res->res, free_table);
156 res->res = NULL;
157 return -1;
160 /* Pointer magic explanation:
161 * The sqlite result is an array such that the first res->sz elements are
162 * the column names and each tuple follows afterwards
163 * ex: (from the sqlite2 documentation)
164 SELECT employee_name, login, host FROM users WHERE login LIKE * 'd%';
166 nrow = 2
167 ncolumn = 3
168 result[0] = "employee_name"
169 result[1] = "login"
170 result[2] = "host"
171 result[3] = "dummy"
172 result[4] = "No such user"
173 result[5] = 0
174 result[6] = "D. Richard Hipp"
175 result[7] = "drh"
176 result[8] = "zadok"
179 row->data = res->res + res->sz + (res->sz * row->n);
181 return 0;
184 static const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
186 if ((n < 0) || (n >= row->res->sz)) {
187 return NULL;
190 return row->data[n];
193 static apr_status_t dbd_sqlite_datum_get(const apr_dbd_row_t *row, int n,
194 apr_dbd_type_e type, void *data)
196 if ((n < 0) || (n >= row->res->sz)) {
197 return APR_EGENERAL;
200 if (row->data[n] == NULL) {
201 return APR_ENOENT;
204 switch (type) {
205 case APR_DBD_TYPE_TINY:
206 *(char*)data = atoi(row->data[n]);
207 break;
208 case APR_DBD_TYPE_UTINY:
209 *(unsigned char*)data = atoi(row->data[n]);
210 break;
211 case APR_DBD_TYPE_SHORT:
212 *(short*)data = atoi(row->data[n]);
213 break;
214 case APR_DBD_TYPE_USHORT:
215 *(unsigned short*)data = atoi(row->data[n]);
216 break;
217 case APR_DBD_TYPE_INT:
218 *(int*)data = atoi(row->data[n]);
219 break;
220 case APR_DBD_TYPE_UINT:
221 *(unsigned int*)data = atoi(row->data[n]);
222 break;
223 case APR_DBD_TYPE_LONG:
224 *(long*)data = atol(row->data[n]);
225 break;
226 case APR_DBD_TYPE_ULONG:
227 *(unsigned long*)data = atol(row->data[n]);
228 break;
229 case APR_DBD_TYPE_LONGLONG:
230 *(apr_int64_t*)data = apr_atoi64(row->data[n]);
231 break;
232 case APR_DBD_TYPE_ULONGLONG:
233 *(apr_uint64_t*)data = apr_atoi64(row->data[n]);
234 break;
235 case APR_DBD_TYPE_FLOAT:
236 *(float*)data = atof(row->data[n]);
237 break;
238 case APR_DBD_TYPE_DOUBLE:
239 *(double*)data = atof(row->data[n]);
240 break;
241 case APR_DBD_TYPE_STRING:
242 case APR_DBD_TYPE_TEXT:
243 case APR_DBD_TYPE_TIME:
244 case APR_DBD_TYPE_DATE:
245 case APR_DBD_TYPE_DATETIME:
246 case APR_DBD_TYPE_TIMESTAMP:
247 case APR_DBD_TYPE_ZTIMESTAMP:
248 *(char**)data = row->data[n];
249 break;
250 case APR_DBD_TYPE_BLOB:
251 case APR_DBD_TYPE_CLOB:
253 apr_bucket *e;
254 apr_bucket_brigade *b = (apr_bucket_brigade*)data;
256 e = apr_bucket_pool_create(row->data[n],strlen(row->data[n]),
257 row->res->pool, b->bucket_alloc);
258 APR_BRIGADE_INSERT_TAIL(b, e);
260 break;
261 case APR_DBD_TYPE_NULL:
262 *(void**)data = NULL;
263 break;
264 default:
265 return APR_EGENERAL;
268 return APR_SUCCESS;
271 static const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
273 return sql->errmsg;
276 static int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
278 char **result;
279 int ret;
280 int tuples = 0;
281 int fields = 0;
283 if (sql->trans && sql->trans->errnum) {
284 return sql->trans->errnum;
287 FREE_ERROR_MSG(sql);
289 ret =
290 sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
291 &sql->errmsg);
292 if (ret == SQLITE_OK) {
293 *nrows = sqlite_changes(sql->conn);
295 if (tuples > 0)
296 free(result);
298 ret = 0;
301 if (TXN_NOTICE_ERRORS(sql->trans)) {
302 sql->trans->errnum = ret;
305 return ret;
308 static apr_status_t free_mem(void *data)
310 sqlite_freemem(data);
311 return APR_SUCCESS;
314 static const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
315 apr_dbd_t * sql)
317 char *ret = sqlite_mprintf("%q", arg);
318 apr_pool_cleanup_register(pool, ret, free_mem, apr_pool_cleanup_null);
319 return ret;
322 static int dbd_sqlite_prepare(apr_pool_t * pool, apr_dbd_t * sql,
323 const char *query, const char *label,
324 int nargs, int nvals, apr_dbd_type_e *types,
325 apr_dbd_prepared_t ** statement)
327 return APR_ENOTIMPL;
330 static int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql,
331 int *nrows, apr_dbd_prepared_t * statement,
332 const char **values)
334 return APR_ENOTIMPL;
337 static int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
338 int *nrows, apr_dbd_prepared_t * statement,
339 va_list args)
341 return APR_ENOTIMPL;
344 static int dbd_sqlite_pselect(apr_pool_t * pool, apr_dbd_t * sql,
345 apr_dbd_results_t ** results,
346 apr_dbd_prepared_t * statement,
347 int seek, const char **values)
349 return APR_ENOTIMPL;
352 static int dbd_sqlite_pvselect(apr_pool_t * pool, apr_dbd_t * sql,
353 apr_dbd_results_t ** results,
354 apr_dbd_prepared_t * statement, int seek,
355 va_list args)
357 return APR_ENOTIMPL;
360 static int dbd_sqlite_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
361 int *nrows, apr_dbd_prepared_t * statement,
362 const void **values)
364 return APR_ENOTIMPL;
367 static int dbd_sqlite_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
368 int *nrows, apr_dbd_prepared_t * statement,
369 va_list args)
371 return APR_ENOTIMPL;
374 static int dbd_sqlite_pbselect(apr_pool_t * pool, apr_dbd_t * sql,
375 apr_dbd_results_t ** results,
376 apr_dbd_prepared_t * statement,
377 int seek, const void **values)
379 return APR_ENOTIMPL;
382 static int dbd_sqlite_pvbselect(apr_pool_t * pool, apr_dbd_t * sql,
383 apr_dbd_results_t ** results,
384 apr_dbd_prepared_t * statement, int seek,
385 va_list args)
387 return APR_ENOTIMPL;
390 static int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
391 apr_dbd_transaction_t ** trans)
393 int ret, rows;
395 ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION");
396 if (ret == 0) {
397 if (!*trans) {
398 *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
400 (*trans)->handle = handle;
401 handle->trans = *trans;
403 else {
404 ret = -1;
406 return ret;
409 static int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
411 int rows;
412 int ret = -1; /* no transaction is an error cond */
414 if (trans) {
415 /* rollback on error or explicit rollback request */
416 if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
417 trans->errnum = 0;
418 ret =
419 dbd_sqlite_query(trans->handle, &rows,
420 "ROLLBACK TRANSACTION");
422 else {
423 ret =
424 dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
426 trans->handle->trans = NULL;
429 return ret;
432 static int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans)
434 if (!trans)
435 return APR_DBD_TRANSACTION_COMMIT;
437 return trans->mode;
440 static int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans,
441 int mode)
443 if (!trans)
444 return APR_DBD_TRANSACTION_COMMIT;
446 return trans->mode = (mode & TXN_MODE_BITS);
449 static apr_status_t error_free(void *data)
451 free(data);
452 return APR_SUCCESS;
455 static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_,
456 const char **error)
458 apr_dbd_t *sql;
459 sqlite *conn = NULL;
460 char *perm;
461 int iperms = 600;
462 char* params = apr_pstrdup(pool, params_);
463 /* params = "[filename]:[permissions]"
464 * example: "shopping.db:600"
467 perm = strstr(params, ":");
468 if (perm) {
469 *(perm++) = '\x00'; /* split the filename and permissions */
471 if (strlen(perm) > 0)
472 iperms = atoi(perm);
475 if (error) {
476 *error = NULL;
478 conn = sqlite_open(params, iperms, (char **)error);
480 if (*error) {
481 apr_pool_cleanup_register(pool, *error, error_free,
482 apr_pool_cleanup_null);
485 else {
486 conn = sqlite_open(params, iperms, NULL);
489 sql = apr_pcalloc(pool, sizeof(*sql));
490 sql->conn = conn;
492 return sql;
495 static apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
497 if (handle->conn) {
498 sqlite_close(handle->conn);
499 handle->conn = NULL;
501 return APR_SUCCESS;
504 static apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
505 apr_dbd_t * handle)
507 if (handle->conn == NULL)
508 return -1;
509 return APR_SUCCESS;
512 static int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
513 const char *name)
515 return APR_ENOTIMPL;
518 static void *dbd_sqlite_native(apr_dbd_t * handle)
520 return handle->conn;
523 static int dbd_sqlite_num_cols(apr_dbd_results_t * res)
525 return res->sz;
528 static int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
530 return res->ntuples;
533 APU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = {
534 "sqlite2",
535 NULL,
536 dbd_sqlite_native,
537 dbd_sqlite_open,
538 dbd_sqlite_check_conn,
539 dbd_sqlite_close,
540 dbd_sqlite_select_db,
541 dbd_sqlite_start_transaction,
542 dbd_sqlite_end_transaction,
543 dbd_sqlite_query,
544 dbd_sqlite_select,
545 dbd_sqlite_num_cols,
546 dbd_sqlite_num_tuples,
547 dbd_sqlite_get_row,
548 dbd_sqlite_get_entry,
549 dbd_sqlite_error,
550 dbd_sqlite_escape,
551 dbd_sqlite_prepare,
552 dbd_sqlite_pvquery,
553 dbd_sqlite_pvselect,
554 dbd_sqlite_pquery,
555 dbd_sqlite_pselect,
556 dbd_sqlite_get_name,
557 dbd_sqlite_transaction_mode_get,
558 dbd_sqlite_transaction_mode_set,
559 NULL,
560 dbd_sqlite_pvbquery,
561 dbd_sqlite_pvbselect,
562 dbd_sqlite_pbquery,
563 dbd_sqlite_pbselect,
564 dbd_sqlite_datum_get
566 #endif