1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251876Speter * contributor license agreements.  See the NOTICE file distributed with
3251876Speter * this work for additional information regarding copyright ownership.
4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251876Speter * (the "License"); you may not use this file except in compliance with
6251876Speter * the License.  You may obtain a copy of the License at
7251876Speter *
8251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251876Speter *
10251876Speter * Unless required by applicable law or agreed to in writing, software
11251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251876Speter * See the License for the specific language governing permissions and
14251876Speter * limitations under the License.
15251876Speter */
16251876Speter
17251876Speter#include "apu.h"
18251876Speter
19251876Speter#if APU_HAVE_SQLITE2
20251876Speter
21251876Speter#include <ctype.h>
22251876Speter#include <stdlib.h>
23251876Speter
24251876Speter#include <sqlite.h>
25251876Speter
26251876Speter#include "apr_strings.h"
27251876Speter#include "apr_time.h"
28251876Speter#include "apr_buckets.h"
29251876Speter
30251876Speter#include "apr_dbd_internal.h"
31251876Speter
32251876Speterstruct apr_dbd_transaction_t {
33251876Speter    int mode;
34251876Speter    int errnum;
35251876Speter    apr_dbd_t *handle;
36251876Speter};
37251876Speter
38251876Speterstruct apr_dbd_t {
39251876Speter    sqlite *conn;
40251876Speter    char *errmsg;
41251876Speter    apr_dbd_transaction_t *trans;
42251876Speter};
43251876Speter
44251876Speterstruct apr_dbd_results_t {
45251876Speter    int random;
46251876Speter    sqlite *handle;
47251876Speter    char **res;
48251876Speter    size_t ntuples;
49251876Speter    size_t sz;
50251876Speter    size_t index;
51251876Speter    apr_pool_t *pool;
52251876Speter};
53251876Speter
54251876Speterstruct apr_dbd_row_t {
55251876Speter    int n;
56251876Speter    char **data;
57251876Speter    apr_dbd_results_t *res;
58251876Speter};
59251876Speter
60251876Speterstruct apr_dbd_prepared_t {
61251876Speter    const char *name;
62251876Speter    int prepared;
63251876Speter};
64251876Speter
65251876Speter#define FREE_ERROR_MSG(dbd) \
66251876Speter	do { \
67251876Speter		if(dbd && dbd->errmsg) { \
68251876Speter			free(dbd->errmsg); \
69251876Speter			dbd->errmsg = NULL; \
70251876Speter		} \
71251876Speter	} while(0);
72251876Speter
73251876Speterstatic apr_status_t free_table(void *data)
74251876Speter{
75251876Speter    sqlite_free_table(data);
76251876Speter    return APR_SUCCESS;
77251876Speter}
78251876Speter
79251876Speterstatic int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql,
80251876Speter                             apr_dbd_results_t ** results, const char *query,
81251876Speter                             int seek)
82251876Speter{
83251876Speter    char **result;
84251876Speter    int ret = 0;
85251876Speter    int tuples = 0;
86251876Speter    int fields = 0;
87251876Speter
88251876Speter    if (sql->trans && sql->trans->errnum) {
89251876Speter        return sql->trans->errnum;
90251876Speter    }
91251876Speter
92251876Speter    FREE_ERROR_MSG(sql);
93251876Speter
94251876Speter    ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
95251876Speter                          &sql->errmsg);
96251876Speter
97251876Speter    if (ret == SQLITE_OK) {
98251876Speter        if (!*results) {
99251876Speter            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
100251876Speter        }
101251876Speter
102251876Speter        (*results)->res = result;
103251876Speter        (*results)->ntuples = tuples;
104251876Speter        (*results)->sz = fields;
105251876Speter        (*results)->random = seek;
106251876Speter        (*results)->pool = pool;
107251876Speter
108251876Speter        if (tuples > 0)
109251876Speter            apr_pool_cleanup_register(pool, result, free_table,
110251876Speter                                      apr_pool_cleanup_null);
111251876Speter
112251876Speter        ret = 0;
113251876Speter    }
114251876Speter    else {
115251876Speter        if (TXN_NOTICE_ERRORS(sql->trans)) {
116251876Speter            sql->trans->errnum = ret;
117251876Speter        }
118251876Speter    }
119251876Speter
120251876Speter    return ret;
121251876Speter}
122251876Speter
123251876Speterstatic const char *dbd_sqlite_get_name(const apr_dbd_results_t *res, int n)
124251876Speter{
125251876Speter    if ((n < 0) || (n >= res->sz)) {
126251876Speter        return NULL;
127251876Speter    }
128251876Speter
129251876Speter    return res->res[n];
130251876Speter}
131251876Speter
132251876Speterstatic int dbd_sqlite_get_row(apr_pool_t * pool, apr_dbd_results_t * res,
133251876Speter                              apr_dbd_row_t ** rowp, int rownum)
134251876Speter{
135251876Speter    apr_dbd_row_t *row = *rowp;
136251876Speter    int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
137251876Speter
138251876Speter    if (row == NULL) {
139251876Speter        row = apr_palloc(pool, sizeof(apr_dbd_row_t));
140251876Speter        *rowp = row;
141251876Speter        row->res = res;
142251876Speter        row->n = sequential ? 0 : rownum - 1;
143251876Speter    }
144251876Speter    else {
145251876Speter        if (sequential) {
146251876Speter            ++row->n;
147251876Speter        }
148251876Speter        else {
149251876Speter            row->n = rownum - 1;
150251876Speter        }
151251876Speter    }
152251876Speter
153251876Speter    if (row->n >= res->ntuples) {
154251876Speter        *rowp = NULL;
155253734Speter        apr_pool_cleanup_run(res->pool, res->res, free_table);
156251876Speter        res->res = NULL;
157251876Speter        return -1;
158251876Speter    }
159251876Speter
160251876Speter    /* Pointer magic explanation:
161251876Speter     *      The sqlite result is an array such that the first res->sz elements are
162251876Speter     *      the column names and each tuple follows afterwards
163251876Speter     *      ex: (from the sqlite2 documentation)
164251876Speter     SELECT employee_name, login, host FROM users WHERE login LIKE *        'd%';
165251876Speter
166251876Speter     nrow = 2
167251876Speter     ncolumn = 3
168251876Speter     result[0] = "employee_name"
169251876Speter     result[1] = "login"
170251876Speter     result[2] = "host"
171251876Speter     result[3] = "dummy"
172251876Speter     result[4] = "No such user"
173251876Speter     result[5] = 0
174251876Speter     result[6] = "D. Richard Hipp"
175251876Speter     result[7] = "drh"
176251876Speter     result[8] = "zadok"
177251876Speter     */
178251876Speter
179251876Speter    row->data = res->res + res->sz + (res->sz * row->n);
180251876Speter
181251876Speter    return 0;
182251876Speter}
183251876Speter
184251876Speterstatic const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
185251876Speter{
186251876Speter    if ((n < 0) || (n >= row->res->sz)) {
187251876Speter      return NULL;
188251876Speter    }
189251876Speter
190251876Speter    return row->data[n];
191251876Speter}
192251876Speter
193251876Speterstatic apr_status_t dbd_sqlite_datum_get(const apr_dbd_row_t *row, int n,
194251876Speter                                         apr_dbd_type_e type, void *data)
195251876Speter{
196251876Speter    if ((n < 0) || (n >= row->res->sz)) {
197251876Speter      return APR_EGENERAL;
198251876Speter    }
199251876Speter
200251876Speter    if (row->data[n] == NULL) {
201251876Speter        return APR_ENOENT;
202251876Speter    }
203251876Speter
204251876Speter    switch (type) {
205251876Speter    case APR_DBD_TYPE_TINY:
206251876Speter        *(char*)data = atoi(row->data[n]);
207251876Speter        break;
208251876Speter    case APR_DBD_TYPE_UTINY:
209251876Speter        *(unsigned char*)data = atoi(row->data[n]);
210251876Speter        break;
211251876Speter    case APR_DBD_TYPE_SHORT:
212251876Speter        *(short*)data = atoi(row->data[n]);
213251876Speter        break;
214251876Speter    case APR_DBD_TYPE_USHORT:
215251876Speter        *(unsigned short*)data = atoi(row->data[n]);
216251876Speter        break;
217251876Speter    case APR_DBD_TYPE_INT:
218251876Speter        *(int*)data = atoi(row->data[n]);
219251876Speter        break;
220251876Speter    case APR_DBD_TYPE_UINT:
221251876Speter        *(unsigned int*)data = atoi(row->data[n]);
222251876Speter        break;
223251876Speter    case APR_DBD_TYPE_LONG:
224251876Speter        *(long*)data = atol(row->data[n]);
225251876Speter        break;
226251876Speter    case APR_DBD_TYPE_ULONG:
227251876Speter        *(unsigned long*)data = atol(row->data[n]);
228251876Speter        break;
229251876Speter    case APR_DBD_TYPE_LONGLONG:
230251876Speter        *(apr_int64_t*)data = apr_atoi64(row->data[n]);
231251876Speter        break;
232251876Speter    case APR_DBD_TYPE_ULONGLONG:
233251876Speter        *(apr_uint64_t*)data = apr_atoi64(row->data[n]);
234251876Speter        break;
235251876Speter    case APR_DBD_TYPE_FLOAT:
236251876Speter        *(float*)data = atof(row->data[n]);
237251876Speter        break;
238251876Speter    case APR_DBD_TYPE_DOUBLE:
239251876Speter        *(double*)data = atof(row->data[n]);
240251876Speter        break;
241251876Speter    case APR_DBD_TYPE_STRING:
242251876Speter    case APR_DBD_TYPE_TEXT:
243251876Speter    case APR_DBD_TYPE_TIME:
244251876Speter    case APR_DBD_TYPE_DATE:
245251876Speter    case APR_DBD_TYPE_DATETIME:
246251876Speter    case APR_DBD_TYPE_TIMESTAMP:
247251876Speter    case APR_DBD_TYPE_ZTIMESTAMP:
248251876Speter        *(char**)data = row->data[n];
249251876Speter        break;
250251876Speter    case APR_DBD_TYPE_BLOB:
251251876Speter    case APR_DBD_TYPE_CLOB:
252251876Speter        {
253251876Speter        apr_bucket *e;
254251876Speter        apr_bucket_brigade *b = (apr_bucket_brigade*)data;
255251876Speter
256251876Speter        e = apr_bucket_pool_create(row->data[n],strlen(row->data[n]),
257251876Speter                                   row->res->pool, b->bucket_alloc);
258251876Speter        APR_BRIGADE_INSERT_TAIL(b, e);
259251876Speter        }
260251876Speter        break;
261251876Speter    case APR_DBD_TYPE_NULL:
262251876Speter        *(void**)data = NULL;
263251876Speter        break;
264251876Speter    default:
265251876Speter        return APR_EGENERAL;
266251876Speter    }
267251876Speter
268251876Speter    return APR_SUCCESS;
269251876Speter}
270251876Speter
271251876Speterstatic const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
272251876Speter{
273251876Speter    return sql->errmsg;
274251876Speter}
275251876Speter
276251876Speterstatic int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
277251876Speter{
278251876Speter    char **result;
279251876Speter    int ret;
280251876Speter    int tuples = 0;
281251876Speter    int fields = 0;
282251876Speter
283251876Speter    if (sql->trans && sql->trans->errnum) {
284251876Speter        return sql->trans->errnum;
285251876Speter    }
286251876Speter
287251876Speter    FREE_ERROR_MSG(sql);
288251876Speter
289251876Speter    ret =
290251876Speter        sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
291251876Speter                         &sql->errmsg);
292251876Speter    if (ret == SQLITE_OK) {
293251876Speter        *nrows = sqlite_changes(sql->conn);
294251876Speter
295251876Speter        if (tuples > 0)
296251876Speter            free(result);
297251876Speter
298251876Speter        ret = 0;
299251876Speter    }
300251876Speter
301251876Speter    if (TXN_NOTICE_ERRORS(sql->trans)) {
302251876Speter        sql->trans->errnum = ret;
303251876Speter    }
304251876Speter
305251876Speter    return ret;
306251876Speter}
307251876Speter
308251876Speterstatic apr_status_t free_mem(void *data)
309251876Speter{
310251876Speter    sqlite_freemem(data);
311251876Speter    return APR_SUCCESS;
312251876Speter}
313251876Speter
314251876Speterstatic const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
315251876Speter                                     apr_dbd_t * sql)
316251876Speter{
317251876Speter    char *ret = sqlite_mprintf("%q", arg);
318251876Speter    apr_pool_cleanup_register(pool, ret, free_mem, apr_pool_cleanup_null);
319251876Speter    return ret;
320251876Speter}
321251876Speter
322251876Speterstatic int dbd_sqlite_prepare(apr_pool_t * pool, apr_dbd_t * sql,
323251876Speter                              const char *query, const char *label,
324251876Speter                              int nargs, int nvals, apr_dbd_type_e *types,
325251876Speter                              apr_dbd_prepared_t ** statement)
326251876Speter{
327251876Speter    return APR_ENOTIMPL;
328251876Speter}
329251876Speter
330251876Speterstatic int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql,
331251876Speter                             int *nrows, apr_dbd_prepared_t * statement,
332251876Speter                             const char **values)
333251876Speter{
334251876Speter    return APR_ENOTIMPL;
335251876Speter}
336251876Speter
337251876Speterstatic int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
338251876Speter                              int *nrows, apr_dbd_prepared_t * statement,
339251876Speter                              va_list args)
340251876Speter{
341251876Speter    return APR_ENOTIMPL;
342251876Speter}
343251876Speter
344251876Speterstatic int dbd_sqlite_pselect(apr_pool_t * pool, apr_dbd_t * sql,
345251876Speter                              apr_dbd_results_t ** results,
346251876Speter                              apr_dbd_prepared_t * statement,
347251876Speter                              int seek, const char **values)
348251876Speter{
349251876Speter    return APR_ENOTIMPL;
350251876Speter}
351251876Speter
352251876Speterstatic int dbd_sqlite_pvselect(apr_pool_t * pool, apr_dbd_t * sql,
353251876Speter                               apr_dbd_results_t ** results,
354251876Speter                               apr_dbd_prepared_t * statement, int seek,
355251876Speter                               va_list args)
356251876Speter{
357251876Speter    return APR_ENOTIMPL;
358251876Speter}
359251876Speter
360251876Speterstatic int dbd_sqlite_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
361251876Speter                              int *nrows, apr_dbd_prepared_t * statement,
362251876Speter                              const void **values)
363251876Speter{
364251876Speter    return APR_ENOTIMPL;
365251876Speter}
366251876Speter
367251876Speterstatic int dbd_sqlite_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
368251876Speter                               int *nrows, apr_dbd_prepared_t * statement,
369251876Speter                               va_list args)
370251876Speter{
371251876Speter    return APR_ENOTIMPL;
372251876Speter}
373251876Speter
374251876Speterstatic int dbd_sqlite_pbselect(apr_pool_t * pool, apr_dbd_t * sql,
375251876Speter                               apr_dbd_results_t ** results,
376251876Speter                               apr_dbd_prepared_t * statement,
377251876Speter                               int seek, const void **values)
378251876Speter{
379251876Speter    return APR_ENOTIMPL;
380251876Speter}
381251876Speter
382251876Speterstatic int dbd_sqlite_pvbselect(apr_pool_t * pool, apr_dbd_t * sql,
383251876Speter                                apr_dbd_results_t ** results,
384251876Speter                                apr_dbd_prepared_t * statement, int seek,
385251876Speter                                va_list args)
386251876Speter{
387251876Speter    return APR_ENOTIMPL;
388251876Speter}
389251876Speter
390251876Speterstatic int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
391251876Speter                                        apr_dbd_transaction_t ** trans)
392251876Speter{
393251876Speter    int ret, rows;
394251876Speter
395251876Speter    ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION");
396251876Speter    if (ret == 0) {
397251876Speter        if (!*trans) {
398251876Speter            *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
399251876Speter        }
400251876Speter        (*trans)->handle = handle;
401251876Speter        handle->trans = *trans;
402251876Speter    }
403251876Speter    else {
404251876Speter        ret = -1;
405251876Speter    }
406251876Speter    return ret;
407251876Speter}
408251876Speter
409251876Speterstatic int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
410251876Speter{
411251876Speter    int rows;
412251876Speter    int ret = -1;               /* no transaction is an error cond */
413251876Speter
414251876Speter    if (trans) {
415251876Speter        /* rollback on error or explicit rollback request */
416251876Speter        if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
417251876Speter            trans->errnum = 0;
418251876Speter            ret =
419251876Speter                dbd_sqlite_query(trans->handle, &rows,
420251876Speter                                 "ROLLBACK TRANSACTION");
421251876Speter        }
422251876Speter        else {
423251876Speter            ret =
424251876Speter                dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
425251876Speter        }
426251876Speter        trans->handle->trans = NULL;
427251876Speter    }
428251876Speter
429251876Speter    return ret;
430251876Speter}
431251876Speter
432251876Speterstatic int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans)
433251876Speter{
434251876Speter    if (!trans)
435251876Speter        return APR_DBD_TRANSACTION_COMMIT;
436251876Speter
437251876Speter    return trans->mode;
438251876Speter}
439251876Speter
440251876Speterstatic int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans,
441251876Speter                                           int mode)
442251876Speter{
443251876Speter    if (!trans)
444251876Speter        return APR_DBD_TRANSACTION_COMMIT;
445251876Speter
446251876Speter    return trans->mode = (mode & TXN_MODE_BITS);
447251876Speter}
448251876Speter
449251876Speterstatic apr_status_t error_free(void *data)
450251876Speter{
451251876Speter    free(data);
452251876Speter    return APR_SUCCESS;
453251876Speter}
454251876Speter
455251876Speterstatic apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_,
456251876Speter                                  const char **error)
457251876Speter{
458251876Speter    apr_dbd_t *sql;
459251876Speter    sqlite *conn = NULL;
460251876Speter    char *perm;
461251876Speter    int iperms = 600;
462251876Speter    char* params = apr_pstrdup(pool, params_);
463251876Speter    /* params = "[filename]:[permissions]"
464251876Speter     *    example: "shopping.db:600"
465251876Speter     */
466251876Speter
467251876Speter    perm = strstr(params, ":");
468251876Speter    if (perm) {
469251876Speter        *(perm++) = '\x00';     /* split the filename and permissions */
470251876Speter
471251876Speter        if (strlen(perm) > 0)
472251876Speter            iperms = atoi(perm);
473251876Speter    }
474251876Speter
475251876Speter    if (error) {
476251876Speter        *error = NULL;
477251876Speter
478251876Speter        conn = sqlite_open(params, iperms, (char **)error);
479251876Speter
480251876Speter        if (*error) {
481251876Speter            apr_pool_cleanup_register(pool, *error, error_free,
482251876Speter                                      apr_pool_cleanup_null);
483251876Speter        }
484251876Speter    }
485251876Speter    else {
486251876Speter        conn = sqlite_open(params, iperms, NULL);
487251876Speter    }
488251876Speter
489251876Speter    sql = apr_pcalloc(pool, sizeof(*sql));
490251876Speter    sql->conn = conn;
491251876Speter
492251876Speter    return sql;
493251876Speter}
494251876Speter
495251876Speterstatic apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
496251876Speter{
497251876Speter    if (handle->conn) {
498251876Speter        sqlite_close(handle->conn);
499251876Speter        handle->conn = NULL;
500251876Speter    }
501251876Speter    return APR_SUCCESS;
502251876Speter}
503251876Speter
504251876Speterstatic apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
505251876Speter                                          apr_dbd_t * handle)
506251876Speter{
507251876Speter    if (handle->conn == NULL)
508251876Speter        return -1;
509251876Speter    return APR_SUCCESS;
510251876Speter}
511251876Speter
512251876Speterstatic int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
513251876Speter                                const char *name)
514251876Speter{
515251876Speter    return APR_ENOTIMPL;
516251876Speter}
517251876Speter
518251876Speterstatic void *dbd_sqlite_native(apr_dbd_t * handle)
519251876Speter{
520251876Speter    return handle->conn;
521251876Speter}
522251876Speter
523251876Speterstatic int dbd_sqlite_num_cols(apr_dbd_results_t * res)
524251876Speter{
525251876Speter    return res->sz;
526251876Speter}
527251876Speter
528251876Speterstatic int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
529251876Speter{
530251876Speter    return res->ntuples;
531251876Speter}
532251876Speter
533251876SpeterAPU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = {
534251876Speter    "sqlite2",
535251876Speter    NULL,
536251876Speter    dbd_sqlite_native,
537251876Speter    dbd_sqlite_open,
538251876Speter    dbd_sqlite_check_conn,
539251876Speter    dbd_sqlite_close,
540251876Speter    dbd_sqlite_select_db,
541251876Speter    dbd_sqlite_start_transaction,
542251876Speter    dbd_sqlite_end_transaction,
543251876Speter    dbd_sqlite_query,
544251876Speter    dbd_sqlite_select,
545251876Speter    dbd_sqlite_num_cols,
546251876Speter    dbd_sqlite_num_tuples,
547251876Speter    dbd_sqlite_get_row,
548251876Speter    dbd_sqlite_get_entry,
549251876Speter    dbd_sqlite_error,
550251876Speter    dbd_sqlite_escape,
551251876Speter    dbd_sqlite_prepare,
552251876Speter    dbd_sqlite_pvquery,
553251876Speter    dbd_sqlite_pvselect,
554251876Speter    dbd_sqlite_pquery,
555251876Speter    dbd_sqlite_pselect,
556251876Speter    dbd_sqlite_get_name,
557251876Speter    dbd_sqlite_transaction_mode_get,
558251876Speter    dbd_sqlite_transaction_mode_set,
559251876Speter    NULL,
560251876Speter    dbd_sqlite_pvbquery,
561251876Speter    dbd_sqlite_pvbselect,
562251876Speter    dbd_sqlite_pbquery,
563251876Speter    dbd_sqlite_pbselect,
564251876Speter    dbd_sqlite_datum_get
565251876Speter};
566251876Speter#endif
567