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 struct apr_dbd_transaction_t {
41 apr_dbd_transaction_t *trans;
44 struct apr_dbd_results_t {
54 struct apr_dbd_row_t {
57 apr_dbd_results_t *res;
60 struct apr_dbd_prepared_t {
65 #define FREE_ERROR_MSG(dbd) \
67 if(dbd && dbd->errmsg) { \
73 static apr_status_t free_table(void *data)
75 sqlite_free_table(data);
79 static int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql,
80 apr_dbd_results_t ** results, const char *query,
88 if (sql->trans && sql->trans->errnum) {
89 return sql->trans->errnum;
94 ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
97 if (ret == SQLITE_OK) {
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;
109 apr_pool_cleanup_register(pool, result, free_table,
110 apr_pool_cleanup_null);
115 if (TXN_NOTICE_ERRORS(sql->trans)) {
116 sql->trans->errnum = ret;
123 static const char *dbd_sqlite_get_name(const apr_dbd_results_t *res, int n)
125 if ((n < 0) || (n >= res->sz)) {
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;
139 row = apr_palloc(pool, sizeof(apr_dbd_row_t));
142 row->n = sequential ? 0 : rownum - 1;
153 if (row->n >= res->ntuples) {
155 apr_pool_cleanup_run(res->pool, res->res, free_table);
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%';
168 result[0] = "employee_name"
172 result[4] = "No such user"
174 result[6] = "D. Richard Hipp"
179 row->data = res->res + res->sz + (res->sz * row->n);
184 static const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
186 if ((n < 0) || (n >= row->res->sz)) {
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)) {
200 if (row->data[n] == NULL) {
205 case APR_DBD_TYPE_TINY:
206 *(char*)data = atoi(row->data[n]);
208 case APR_DBD_TYPE_UTINY:
209 *(unsigned char*)data = atoi(row->data[n]);
211 case APR_DBD_TYPE_SHORT:
212 *(short*)data = atoi(row->data[n]);
214 case APR_DBD_TYPE_USHORT:
215 *(unsigned short*)data = atoi(row->data[n]);
217 case APR_DBD_TYPE_INT:
218 *(int*)data = atoi(row->data[n]);
220 case APR_DBD_TYPE_UINT:
221 *(unsigned int*)data = atoi(row->data[n]);
223 case APR_DBD_TYPE_LONG:
224 *(long*)data = atol(row->data[n]);
226 case APR_DBD_TYPE_ULONG:
227 *(unsigned long*)data = atol(row->data[n]);
229 case APR_DBD_TYPE_LONGLONG:
230 *(apr_int64_t*)data = apr_atoi64(row->data[n]);
232 case APR_DBD_TYPE_ULONGLONG:
233 *(apr_uint64_t*)data = apr_atoi64(row->data[n]);
235 case APR_DBD_TYPE_FLOAT:
236 *(float*)data = atof(row->data[n]);
238 case APR_DBD_TYPE_DOUBLE:
239 *(double*)data = atof(row->data[n]);
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];
250 case APR_DBD_TYPE_BLOB:
251 case APR_DBD_TYPE_CLOB:
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);
261 case APR_DBD_TYPE_NULL:
262 *(void**)data = NULL;
271 static const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
276 static int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
283 if (sql->trans && sql->trans->errnum) {
284 return sql->trans->errnum;
290 sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
292 if (ret == SQLITE_OK) {
293 *nrows = sqlite_changes(sql->conn);
301 if (TXN_NOTICE_ERRORS(sql->trans)) {
302 sql->trans->errnum = ret;
308 static apr_status_t free_mem(void *data)
310 sqlite_freemem(data);
314 static const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
317 char *ret = sqlite_mprintf("%q", arg);
318 apr_pool_cleanup_register(pool, ret, free_mem, apr_pool_cleanup_null);
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)
330 static int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql,
331 int *nrows, apr_dbd_prepared_t * statement,
337 static int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
338 int *nrows, apr_dbd_prepared_t * statement,
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)
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,
360 static int dbd_sqlite_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
361 int *nrows, apr_dbd_prepared_t * statement,
367 static int dbd_sqlite_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
368 int *nrows, apr_dbd_prepared_t * statement,
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)
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,
390 static int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
391 apr_dbd_transaction_t ** trans)
395 ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION");
398 *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
400 (*trans)->handle = handle;
401 handle->trans = *trans;
409 static int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
412 int ret = -1; /* no transaction is an error cond */
415 /* rollback on error or explicit rollback request */
416 if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
419 dbd_sqlite_query(trans->handle, &rows,
420 "ROLLBACK TRANSACTION");
424 dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
426 trans->handle->trans = NULL;
432 static int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans)
435 return APR_DBD_TRANSACTION_COMMIT;
440 static int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans,
444 return APR_DBD_TRANSACTION_COMMIT;
446 return trans->mode = (mode & TXN_MODE_BITS);
449 static apr_status_t error_free(void *data)
455 static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_,
462 char* params = apr_pstrdup(pool, params_);
463 /* params = "[filename]:[permissions]"
464 * example: "shopping.db:600"
467 perm = strstr(params, ":");
469 *(perm++) = '\x00'; /* split the filename and permissions */
471 if (strlen(perm) > 0)
478 conn = sqlite_open(params, iperms, (char **)error);
481 apr_pool_cleanup_register(pool, *error, error_free,
482 apr_pool_cleanup_null);
486 conn = sqlite_open(params, iperms, NULL);
489 sql = apr_pcalloc(pool, sizeof(*sql));
495 static apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
498 sqlite_close(handle->conn);
504 static apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
507 if (handle->conn == NULL)
512 static int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
518 static void *dbd_sqlite_native(apr_dbd_t * handle)
523 static int dbd_sqlite_num_cols(apr_dbd_results_t * res)
528 static int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
533 APU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = {
538 dbd_sqlite_check_conn,
540 dbd_sqlite_select_db,
541 dbd_sqlite_start_transaction,
542 dbd_sqlite_end_transaction,
546 dbd_sqlite_num_tuples,
548 dbd_sqlite_get_entry,
557 dbd_sqlite_transaction_mode_get,
558 dbd_sqlite_transaction_mode_set,
561 dbd_sqlite_pvbselect,