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
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#include "apu.h"
18
19#if APU_HAVE_SQLITE2
20
21#include <ctype.h>
22#include <stdlib.h>
23
24#include <sqlite.h>
25
26#include "apr_strings.h"
27#include "apr_time.h"
28#include "apr_buckets.h"
29
30#include "apr_dbd_internal.h"
31
32struct apr_dbd_transaction_t {
33    int mode;
34    int errnum;
35    apr_dbd_t *handle;
36};
37
38struct apr_dbd_t {
39    sqlite *conn;
40    char *errmsg;
41    apr_dbd_transaction_t *trans;
42};
43
44struct 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;
52};
53
54struct apr_dbd_row_t {
55    int n;
56    char **data;
57    apr_dbd_results_t *res;
58};
59
60struct apr_dbd_prepared_t {
61    const char *name;
62    int prepared;
63};
64
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);
72
73static apr_status_t free_table(void *data)
74{
75    sqlite_free_table(data);
76    return APR_SUCCESS;
77}
78
79static int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql,
80                             apr_dbd_results_t ** results, const char *query,
81                             int seek)
82{
83    char **result;
84    int ret = 0;
85    int tuples = 0;
86    int fields = 0;
87
88    if (sql->trans && sql->trans->errnum) {
89        return sql->trans->errnum;
90    }
91
92    FREE_ERROR_MSG(sql);
93
94    ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
95                          &sql->errmsg);
96
97    if (ret == SQLITE_OK) {
98        if (!*results) {
99            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
100        }
101
102        (*results)->res = result;
103        (*results)->ntuples = tuples;
104        (*results)->sz = fields;
105        (*results)->random = seek;
106        (*results)->pool = pool;
107
108        if (tuples > 0)
109            apr_pool_cleanup_register(pool, result, free_table,
110                                      apr_pool_cleanup_null);
111
112        ret = 0;
113    }
114    else {
115        if (TXN_NOTICE_ERRORS(sql->trans)) {
116            sql->trans->errnum = ret;
117        }
118    }
119
120    return ret;
121}
122
123static const char *dbd_sqlite_get_name(const apr_dbd_results_t *res, int n)
124{
125    if ((n < 0) || (n >= res->sz)) {
126        return NULL;
127    }
128
129    return res->res[n];
130}
131
132static int dbd_sqlite_get_row(apr_pool_t * pool, apr_dbd_results_t * res,
133                              apr_dbd_row_t ** rowp, int rownum)
134{
135    apr_dbd_row_t *row = *rowp;
136    int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
137
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;
143    }
144    else {
145        if (sequential) {
146            ++row->n;
147        }
148        else {
149            row->n = rownum - 1;
150        }
151    }
152
153    if (row->n >= res->ntuples) {
154        *rowp = NULL;
155        apr_pool_cleanup_run(res->pool, res->res, free_table);
156        res->res = NULL;
157        return -1;
158    }
159
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%';
165
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"
177     */
178
179    row->data = res->res + res->sz + (res->sz * row->n);
180
181    return 0;
182}
183
184static const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
185{
186    if ((n < 0) || (n >= row->res->sz)) {
187      return NULL;
188    }
189
190    return row->data[n];
191}
192
193static apr_status_t dbd_sqlite_datum_get(const apr_dbd_row_t *row, int n,
194                                         apr_dbd_type_e type, void *data)
195{
196    if ((n < 0) || (n >= row->res->sz)) {
197      return APR_EGENERAL;
198    }
199
200    if (row->data[n] == NULL) {
201        return APR_ENOENT;
202    }
203
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:
252        {
253        apr_bucket *e;
254        apr_bucket_brigade *b = (apr_bucket_brigade*)data;
255
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);
259        }
260        break;
261    case APR_DBD_TYPE_NULL:
262        *(void**)data = NULL;
263        break;
264    default:
265        return APR_EGENERAL;
266    }
267
268    return APR_SUCCESS;
269}
270
271static const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
272{
273    return sql->errmsg;
274}
275
276static int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
277{
278    char **result;
279    int ret;
280    int tuples = 0;
281    int fields = 0;
282
283    if (sql->trans && sql->trans->errnum) {
284        return sql->trans->errnum;
285    }
286
287    FREE_ERROR_MSG(sql);
288
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);
294
295        if (tuples > 0)
296            free(result);
297
298        ret = 0;
299    }
300
301    if (TXN_NOTICE_ERRORS(sql->trans)) {
302        sql->trans->errnum = ret;
303    }
304
305    return ret;
306}
307
308static apr_status_t free_mem(void *data)
309{
310    sqlite_freemem(data);
311    return APR_SUCCESS;
312}
313
314static const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
315                                     apr_dbd_t * sql)
316{
317    char *ret = sqlite_mprintf("%q", arg);
318    apr_pool_cleanup_register(pool, ret, free_mem, apr_pool_cleanup_null);
319    return ret;
320}
321
322static 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)
326{
327    return APR_ENOTIMPL;
328}
329
330static int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql,
331                             int *nrows, apr_dbd_prepared_t * statement,
332                             const char **values)
333{
334    return APR_ENOTIMPL;
335}
336
337static int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
338                              int *nrows, apr_dbd_prepared_t * statement,
339                              va_list args)
340{
341    return APR_ENOTIMPL;
342}
343
344static 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)
348{
349    return APR_ENOTIMPL;
350}
351
352static 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)
356{
357    return APR_ENOTIMPL;
358}
359
360static int dbd_sqlite_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
361                              int *nrows, apr_dbd_prepared_t * statement,
362                              const void **values)
363{
364    return APR_ENOTIMPL;
365}
366
367static int dbd_sqlite_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
368                               int *nrows, apr_dbd_prepared_t * statement,
369                               va_list args)
370{
371    return APR_ENOTIMPL;
372}
373
374static 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)
378{
379    return APR_ENOTIMPL;
380}
381
382static 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)
386{
387    return APR_ENOTIMPL;
388}
389
390static int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
391                                        apr_dbd_transaction_t ** trans)
392{
393    int ret, rows;
394
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));
399        }
400        (*trans)->handle = handle;
401        handle->trans = *trans;
402    }
403    else {
404        ret = -1;
405    }
406    return ret;
407}
408
409static int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
410{
411    int rows;
412    int ret = -1;               /* no transaction is an error cond */
413
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");
421        }
422        else {
423            ret =
424                dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
425        }
426        trans->handle->trans = NULL;
427    }
428
429    return ret;
430}
431
432static int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans)
433{
434    if (!trans)
435        return APR_DBD_TRANSACTION_COMMIT;
436
437    return trans->mode;
438}
439
440static int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans,
441                                           int mode)
442{
443    if (!trans)
444        return APR_DBD_TRANSACTION_COMMIT;
445
446    return trans->mode = (mode & TXN_MODE_BITS);
447}
448
449static apr_status_t error_free(void *data)
450{
451    free(data);
452    return APR_SUCCESS;
453}
454
455static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_,
456                                  const char **error)
457{
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"
465     */
466
467    perm = strstr(params, ":");
468    if (perm) {
469        *(perm++) = '\x00';     /* split the filename and permissions */
470
471        if (strlen(perm) > 0)
472            iperms = atoi(perm);
473    }
474
475    if (error) {
476        *error = NULL;
477
478        conn = sqlite_open(params, iperms, (char **)error);
479
480        if (*error) {
481            apr_pool_cleanup_register(pool, *error, error_free,
482                                      apr_pool_cleanup_null);
483        }
484    }
485    else {
486        conn = sqlite_open(params, iperms, NULL);
487    }
488
489    sql = apr_pcalloc(pool, sizeof(*sql));
490    sql->conn = conn;
491
492    return sql;
493}
494
495static apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
496{
497    if (handle->conn) {
498        sqlite_close(handle->conn);
499        handle->conn = NULL;
500    }
501    return APR_SUCCESS;
502}
503
504static apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
505                                          apr_dbd_t * handle)
506{
507    if (handle->conn == NULL)
508        return -1;
509    return APR_SUCCESS;
510}
511
512static int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
513                                const char *name)
514{
515    return APR_ENOTIMPL;
516}
517
518static void *dbd_sqlite_native(apr_dbd_t * handle)
519{
520    return handle->conn;
521}
522
523static int dbd_sqlite_num_cols(apr_dbd_results_t * res)
524{
525    return res->sz;
526}
527
528static int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
529{
530    return res->ntuples;
531}
532
533APU_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
565};
566#endif
567