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_SQLITE3
20251876Speter
21251876Speter#include <ctype.h>
22251876Speter#include <stdlib.h>
23251876Speter
24251876Speter#include <sqlite3.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
32251876Speter#define MAX_RETRY_COUNT 15
33251876Speter#define MAX_RETRY_SLEEP 100000
34251876Speter
35251876Speterstruct apr_dbd_transaction_t {
36251876Speter    int mode;
37251876Speter    int errnum;
38251876Speter    apr_dbd_t *handle;
39251876Speter};
40251876Speter
41251876Speterstruct apr_dbd_t {
42251876Speter    sqlite3 *conn;
43251876Speter    apr_dbd_transaction_t *trans;
44251876Speter    apr_pool_t *pool;
45251876Speter    apr_dbd_prepared_t *prep;
46251876Speter};
47251876Speter
48251876Spetertypedef struct {
49251876Speter    char *name;
50251876Speter    char *value;
51251876Speter    int size;
52251876Speter    int type;
53251876Speter} apr_dbd_column_t;
54251876Speter
55251876Speterstruct apr_dbd_row_t {
56251876Speter    apr_dbd_results_t *res;
57251876Speter    apr_dbd_column_t **columns;
58251876Speter    apr_dbd_row_t *next_row;
59251876Speter    int columnCount;
60251876Speter    int rownum;
61251876Speter};
62251876Speter
63251876Speterstruct apr_dbd_results_t {
64251876Speter    int random;
65251876Speter    sqlite3 *handle;
66251876Speter    sqlite3_stmt *stmt;
67251876Speter    apr_dbd_row_t *next_row;
68251876Speter    size_t sz;
69251876Speter    int tuples;
70251876Speter    char **col_names;
71251876Speter    apr_pool_t *pool;
72251876Speter};
73251876Speter
74251876Speterstruct apr_dbd_prepared_t {
75251876Speter    sqlite3_stmt *stmt;
76251876Speter    apr_dbd_prepared_t *next;
77251876Speter    int nargs;
78251876Speter    int nvals;
79251876Speter    apr_dbd_type_e *types;
80251876Speter};
81251876Speter
82251876Speter#define dbd_sqlite3_is_success(x) (((x) == SQLITE_DONE) || ((x) == SQLITE_OK))
83251876Speter
84251876Speterstatic int dbd_sqlite3_select_internal(apr_pool_t *pool,
85251876Speter                                       apr_dbd_t *sql,
86251876Speter                                       apr_dbd_results_t **results,
87251876Speter                                       sqlite3_stmt *stmt, int seek)
88251876Speter{
89251876Speter    int ret, retry_count = 0, column_count;
90251876Speter    size_t i, num_tuples = 0;
91251876Speter    int increment = 0;
92251876Speter    apr_dbd_row_t *row = NULL;
93251876Speter    apr_dbd_row_t *lastrow = NULL;
94251876Speter    apr_dbd_column_t *column;
95251876Speter    char *hold = NULL;
96251876Speter
97251876Speter    column_count = sqlite3_column_count(stmt);
98251876Speter    if (!*results) {
99251876Speter        *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
100251876Speter    }
101251876Speter    (*results)->stmt = stmt;
102251876Speter    (*results)->sz = column_count;
103251876Speter    (*results)->random = seek;
104251876Speter    (*results)->next_row = 0;
105251876Speter    (*results)->tuples = 0;
106251876Speter    (*results)->col_names = apr_pcalloc(pool, column_count * sizeof(char *));
107251876Speter    (*results)->pool = pool;
108251876Speter    do {
109251876Speter        ret = sqlite3_step(stmt);
110251876Speter        if (ret == SQLITE_BUSY) {
111251876Speter            if (retry_count++ > MAX_RETRY_COUNT) {
112251876Speter                ret = SQLITE_ERROR;
113251876Speter            } else {
114251876Speter                apr_dbd_mutex_unlock();
115251876Speter                apr_sleep(MAX_RETRY_SLEEP);
116251876Speter                apr_dbd_mutex_lock();
117251876Speter            }
118251876Speter        } else if (ret == SQLITE_ROW) {
119251876Speter            int length;
120251876Speter            row = apr_palloc(pool, sizeof(apr_dbd_row_t));
121251876Speter            row->res = *results;
122251876Speter            increment = sizeof(apr_dbd_column_t *);
123251876Speter            length = increment * (*results)->sz;
124251876Speter            row->columns = apr_palloc(pool, length);
125251876Speter            row->columnCount = column_count;
126251876Speter            for (i = 0; i < (*results)->sz; i++) {
127251876Speter                column = apr_palloc(pool, sizeof(apr_dbd_column_t));
128251876Speter                row->columns[i] = column;
129251876Speter                /* copy column name once only */
130251876Speter                if ((*results)->col_names[i] == NULL) {
131251876Speter                    (*results)->col_names[i] =
132251876Speter                        apr_pstrdup(pool, sqlite3_column_name(stmt, i));
133251876Speter                }
134251876Speter                column->name = (*results)->col_names[i];
135251876Speter                column->size = sqlite3_column_bytes(stmt, i);
136251876Speter                column->type = sqlite3_column_type(stmt, i);
137251876Speter                column->value = NULL;
138251876Speter                switch (column->type) {
139251876Speter                case SQLITE_FLOAT:
140251876Speter                case SQLITE_INTEGER:
141251876Speter                case SQLITE_TEXT:
142251876Speter                    hold = (char *) sqlite3_column_text(stmt, i);
143251876Speter                    if (hold) {
144251876Speter                        column->value = apr_pstrmemdup(pool, hold,
145251876Speter                                                       column->size);
146251876Speter                    }
147251876Speter                    break;
148251876Speter                case SQLITE_BLOB:
149251876Speter                    hold = (char *) sqlite3_column_blob(stmt, i);
150251876Speter                    if (hold) {
151251876Speter                        column->value = apr_pstrmemdup(pool, hold,
152251876Speter                                                       column->size);
153251876Speter                    }
154251876Speter                    break;
155251876Speter                case SQLITE_NULL:
156251876Speter                    break;
157251876Speter                }
158251876Speter            }
159251876Speter            row->rownum = num_tuples++;
160251876Speter            row->next_row = 0;
161251876Speter            (*results)->tuples = num_tuples;
162251876Speter            if ((*results)->next_row == 0) {
163251876Speter                (*results)->next_row = row;
164251876Speter            }
165251876Speter            if (lastrow != 0) {
166251876Speter                lastrow->next_row = row;
167251876Speter            }
168251876Speter            lastrow = row;
169251876Speter        }
170251876Speter    } while (ret == SQLITE_ROW || ret == SQLITE_BUSY);
171251876Speter
172251876Speter    if (dbd_sqlite3_is_success(ret)) {
173251876Speter        ret = 0;
174251876Speter    }
175251876Speter    return ret;
176251876Speter}
177251876Speter
178251876Speterstatic int dbd_sqlite3_select(apr_pool_t *pool, apr_dbd_t *sql,
179251876Speter                              apr_dbd_results_t **results, const char *query,
180251876Speter                              int seek)
181251876Speter{
182251876Speter    sqlite3_stmt *stmt = NULL;
183251876Speter    const char *tail = NULL;
184251876Speter    int ret;
185251876Speter
186251876Speter    if (sql->trans && sql->trans->errnum) {
187251876Speter        return sql->trans->errnum;
188251876Speter    }
189251876Speter
190251876Speter    apr_dbd_mutex_lock();
191251876Speter
192251876Speter    ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail);
193251876Speter    if (dbd_sqlite3_is_success(ret)) {
194251876Speter        ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
195251876Speter    }
196251876Speter    sqlite3_finalize(stmt);
197251876Speter
198251876Speter    apr_dbd_mutex_unlock();
199251876Speter
200251876Speter    if (TXN_NOTICE_ERRORS(sql->trans)) {
201251876Speter        sql->trans->errnum = ret;
202251876Speter    }
203251876Speter    return ret;
204251876Speter}
205251876Speter
206251876Speterstatic const char *dbd_sqlite3_get_name(const apr_dbd_results_t *res, int n)
207251876Speter{
208251876Speter    if ((n < 0) || ((size_t)n >= res->sz)) {
209251876Speter        return NULL;
210251876Speter    }
211251876Speter
212251876Speter    return res->col_names[n];
213251876Speter}
214251876Speter
215251876Speterstatic int dbd_sqlite3_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
216251876Speter                               apr_dbd_row_t **rowp, int rownum)
217251876Speter{
218251876Speter    int i = 0;
219251876Speter
220251876Speter    if (rownum == -1) {
221251876Speter        *rowp = res->next_row;
222251876Speter        if (*rowp == 0)
223251876Speter            return -1;
224251876Speter        res->next_row = (*rowp)->next_row;
225251876Speter        return 0;
226251876Speter    }
227251876Speter    if (rownum > res->tuples) {
228251876Speter        return -1;
229251876Speter    }
230251876Speter    rownum--;
231251876Speter    *rowp = res->next_row;
232251876Speter    for (; *rowp != 0; i++, *rowp = (*rowp)->next_row) {
233251876Speter        if (i == rownum) {
234251876Speter            return 0;
235251876Speter        }
236251876Speter    }
237251876Speter
238251876Speter    return -1;
239251876Speter
240251876Speter}
241251876Speter
242251876Speterstatic const char *dbd_sqlite3_get_entry(const apr_dbd_row_t *row, int n)
243251876Speter{
244251876Speter    apr_dbd_column_t *column;
245251876Speter    const char *value;
246251876Speter    if ((n < 0) || (n >= row->columnCount)) {
247251876Speter        return NULL;
248251876Speter    }
249251876Speter    column = row->columns[n];
250251876Speter    value = column->value;
251251876Speter    return value;
252251876Speter}
253251876Speter
254251876Speterstatic apr_status_t dbd_sqlite3_datum_get(const apr_dbd_row_t *row, int n,
255251876Speter                                          apr_dbd_type_e type, void *data)
256251876Speter{
257251876Speter    if ((n < 0) || ((size_t)n >= row->res->sz)) {
258251876Speter      return APR_EGENERAL;
259251876Speter    }
260251876Speter
261251876Speter    if (row->columns[n]->type == SQLITE_NULL) {
262251876Speter        return APR_ENOENT;
263251876Speter    }
264251876Speter
265251876Speter    switch (type) {
266251876Speter    case APR_DBD_TYPE_TINY:
267251876Speter        *(char*)data = atoi(row->columns[n]->value);
268251876Speter        break;
269251876Speter    case APR_DBD_TYPE_UTINY:
270251876Speter        *(unsigned char*)data = atoi(row->columns[n]->value);
271251876Speter        break;
272251876Speter    case APR_DBD_TYPE_SHORT:
273251876Speter        *(short*)data = atoi(row->columns[n]->value);
274251876Speter        break;
275251876Speter    case APR_DBD_TYPE_USHORT:
276251876Speter        *(unsigned short*)data = atoi(row->columns[n]->value);
277251876Speter        break;
278251876Speter    case APR_DBD_TYPE_INT:
279251876Speter        *(int*)data = atoi(row->columns[n]->value);
280251876Speter        break;
281251876Speter    case APR_DBD_TYPE_UINT:
282251876Speter        *(unsigned int*)data = atoi(row->columns[n]->value);
283251876Speter        break;
284251876Speter    case APR_DBD_TYPE_LONG:
285251876Speter        *(long*)data = atol(row->columns[n]->value);
286251876Speter        break;
287251876Speter    case APR_DBD_TYPE_ULONG:
288251876Speter        *(unsigned long*)data = atol(row->columns[n]->value);
289251876Speter        break;
290251876Speter    case APR_DBD_TYPE_LONGLONG:
291251876Speter        *(apr_int64_t*)data = apr_atoi64(row->columns[n]->value);
292251876Speter        break;
293251876Speter    case APR_DBD_TYPE_ULONGLONG:
294251876Speter        *(apr_uint64_t*)data = apr_atoi64(row->columns[n]->value);
295251876Speter        break;
296251876Speter    case APR_DBD_TYPE_FLOAT:
297251876Speter        *(float*)data = (float)atof(row->columns[n]->value);
298251876Speter        break;
299251876Speter    case APR_DBD_TYPE_DOUBLE:
300251876Speter        *(double*)data = atof(row->columns[n]->value);
301251876Speter        break;
302251876Speter    case APR_DBD_TYPE_STRING:
303251876Speter    case APR_DBD_TYPE_TEXT:
304251876Speter    case APR_DBD_TYPE_TIME:
305251876Speter    case APR_DBD_TYPE_DATE:
306251876Speter    case APR_DBD_TYPE_DATETIME:
307251876Speter    case APR_DBD_TYPE_TIMESTAMP:
308251876Speter    case APR_DBD_TYPE_ZTIMESTAMP:
309251876Speter        *(char**)data = row->columns[n]->value;
310251876Speter        break;
311251876Speter    case APR_DBD_TYPE_BLOB:
312251876Speter    case APR_DBD_TYPE_CLOB:
313251876Speter        {
314251876Speter        apr_bucket *e;
315251876Speter        apr_bucket_brigade *b = (apr_bucket_brigade*)data;
316251876Speter
317251876Speter        e = apr_bucket_pool_create(row->columns[n]->value,
318251876Speter                                   row->columns[n]->size,
319251876Speter                                   row->res->pool, b->bucket_alloc);
320251876Speter        APR_BRIGADE_INSERT_TAIL(b, e);
321251876Speter        }
322251876Speter        break;
323251876Speter    case APR_DBD_TYPE_NULL:
324251876Speter        *(void**)data = NULL;
325251876Speter        break;
326251876Speter    default:
327251876Speter        return APR_EGENERAL;
328251876Speter    }
329251876Speter
330251876Speter    return APR_SUCCESS;
331251876Speter}
332251876Speter
333251876Speterstatic const char *dbd_sqlite3_error(apr_dbd_t *sql, int n)
334251876Speter{
335251876Speter    return sqlite3_errmsg(sql->conn);
336251876Speter}
337251876Speter
338251876Speterstatic int dbd_sqlite3_query_internal(apr_dbd_t *sql, sqlite3_stmt *stmt,
339251876Speter                                      int *nrows)
340251876Speter{
341251876Speter    int ret = -1, retry_count = 0;
342251876Speter
343251876Speter    while(retry_count++ <= MAX_RETRY_COUNT) {
344251876Speter        ret = sqlite3_step(stmt);
345251876Speter        if (ret != SQLITE_BUSY)
346251876Speter            break;
347251876Speter
348251876Speter        apr_dbd_mutex_unlock();
349251876Speter        apr_sleep(MAX_RETRY_SLEEP);
350251876Speter        apr_dbd_mutex_lock();
351251876Speter    }
352251876Speter
353251876Speter    *nrows = sqlite3_changes(sql->conn);
354251876Speter
355251876Speter    if (dbd_sqlite3_is_success(ret)) {
356251876Speter        ret = 0;
357251876Speter    }
358251876Speter    return ret;
359251876Speter}
360251876Speter
361251876Speterstatic int dbd_sqlite3_query(apr_dbd_t *sql, int *nrows, const char *query)
362251876Speter{
363251876Speter    sqlite3_stmt *stmt = NULL;
364251876Speter    const char *tail = NULL;
365251876Speter    int ret = -1, length = 0;
366251876Speter
367251876Speter    if (sql->trans && sql->trans->errnum) {
368251876Speter        return sql->trans->errnum;
369251876Speter    }
370251876Speter
371251876Speter    length = strlen(query);
372251876Speter    apr_dbd_mutex_lock();
373251876Speter
374251876Speter    do {
375251876Speter        ret = sqlite3_prepare(sql->conn, query, length, &stmt, &tail);
376251876Speter        if (ret != SQLITE_OK) {
377251876Speter            sqlite3_finalize(stmt);
378251876Speter            break;
379251876Speter        }
380251876Speter
381251876Speter        ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
382251876Speter
383251876Speter        sqlite3_finalize(stmt);
384251876Speter        length -= (tail - query);
385251876Speter        query = tail;
386251876Speter    } while (length > 0);
387251876Speter
388251876Speter    apr_dbd_mutex_unlock();
389251876Speter
390251876Speter    if (TXN_NOTICE_ERRORS(sql->trans)) {
391251876Speter        sql->trans->errnum = ret;
392251876Speter    }
393251876Speter    return ret;
394251876Speter}
395251876Speter
396251876Speterstatic apr_status_t free_mem(void *data)
397251876Speter{
398251876Speter    sqlite3_free(data);
399251876Speter    return APR_SUCCESS;
400251876Speter}
401251876Speter
402251876Speterstatic const char *dbd_sqlite3_escape(apr_pool_t *pool, const char *arg,
403251876Speter                                      apr_dbd_t *sql)
404251876Speter{
405251876Speter    char *ret = sqlite3_mprintf("%q", arg);
406251876Speter    apr_pool_cleanup_register(pool, ret, free_mem,
407251876Speter                              apr_pool_cleanup_null);
408251876Speter    return ret;
409251876Speter}
410251876Speter
411251876Speterstatic int dbd_sqlite3_prepare(apr_pool_t *pool, apr_dbd_t *sql,
412251876Speter                               const char *query, const char *label,
413251876Speter                               int nargs, int nvals, apr_dbd_type_e *types,
414251876Speter                               apr_dbd_prepared_t **statement)
415251876Speter{
416251876Speter    sqlite3_stmt *stmt;
417251876Speter    const char *tail = NULL;
418251876Speter    int ret;
419251876Speter
420251876Speter    apr_dbd_mutex_lock();
421251876Speter
422251876Speter    ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail);
423251876Speter    if (ret == SQLITE_OK) {
424251876Speter        apr_dbd_prepared_t *prep;
425251876Speter
426251876Speter        prep = apr_pcalloc(sql->pool, sizeof(*prep));
427251876Speter        prep->stmt = stmt;
428251876Speter        prep->next = sql->prep;
429251876Speter        prep->nargs = nargs;
430251876Speter        prep->nvals = nvals;
431251876Speter        prep->types = types;
432251876Speter
433251876Speter        /* link new statement to the handle */
434251876Speter        sql->prep = prep;
435251876Speter
436251876Speter        *statement = prep;
437251876Speter    } else {
438251876Speter        sqlite3_finalize(stmt);
439251876Speter    }
440251876Speter
441251876Speter    apr_dbd_mutex_unlock();
442251876Speter
443251876Speter    return ret;
444251876Speter}
445251876Speter
446251876Speterstatic void dbd_sqlite3_bind(apr_dbd_prepared_t *statement, const char **values)
447251876Speter{
448251876Speter    sqlite3_stmt *stmt = statement->stmt;
449251876Speter    int i, j;
450251876Speter
451251876Speter    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
452251876Speter        if (values[j] == NULL) {
453251876Speter            sqlite3_bind_null(stmt, i + 1);
454251876Speter        }
455251876Speter        else {
456251876Speter            switch (statement->types[i]) {
457251876Speter            case APR_DBD_TYPE_BLOB:
458251876Speter            case APR_DBD_TYPE_CLOB:
459251876Speter                {
460251876Speter                char *data = (char *)values[j];
461251876Speter                int size = atoi((char*)values[++j]);
462251876Speter
463251876Speter                /* skip table and column */
464251876Speter                j += 2;
465251876Speter
466251876Speter                sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC);
467251876Speter                }
468251876Speter                break;
469251876Speter            default:
470251876Speter                sqlite3_bind_text(stmt, i + 1, values[j],
471251876Speter                                  strlen(values[j]), SQLITE_STATIC);
472251876Speter                break;
473251876Speter            }
474251876Speter        }
475251876Speter    }
476251876Speter
477251876Speter    return;
478251876Speter}
479251876Speter
480251876Speterstatic int dbd_sqlite3_pquery(apr_pool_t *pool, apr_dbd_t *sql,
481251876Speter                              int *nrows, apr_dbd_prepared_t *statement,
482251876Speter                              const char **values)
483251876Speter{
484251876Speter    sqlite3_stmt *stmt = statement->stmt;
485251876Speter    int ret = -1;
486251876Speter
487251876Speter    if (sql->trans && sql->trans->errnum) {
488251876Speter        return sql->trans->errnum;
489251876Speter    }
490251876Speter
491251876Speter    apr_dbd_mutex_lock();
492251876Speter
493251876Speter    ret = sqlite3_reset(stmt);
494251876Speter    if (ret == SQLITE_OK) {
495251876Speter        dbd_sqlite3_bind(statement, values);
496251876Speter
497251876Speter        ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
498251876Speter
499251876Speter        sqlite3_reset(stmt);
500251876Speter    }
501251876Speter
502251876Speter    apr_dbd_mutex_unlock();
503251876Speter
504251876Speter    if (TXN_NOTICE_ERRORS(sql->trans)) {
505251876Speter        sql->trans->errnum = ret;
506251876Speter    }
507251876Speter    return ret;
508251876Speter}
509251876Speter
510251876Speterstatic int dbd_sqlite3_pvquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
511251876Speter                               apr_dbd_prepared_t *statement, va_list args)
512251876Speter{
513251876Speter    const char **values;
514251876Speter    int i;
515251876Speter
516251876Speter    if (sql->trans && sql->trans->errnum) {
517251876Speter        return sql->trans->errnum;
518251876Speter    }
519251876Speter
520251876Speter    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
521251876Speter
522251876Speter    for (i = 0; i < statement->nvals; i++) {
523251876Speter        values[i] = va_arg(args, const char*);
524251876Speter    }
525251876Speter
526251876Speter    return dbd_sqlite3_pquery(pool, sql, nrows, statement, values);
527251876Speter}
528251876Speter
529251876Speterstatic int dbd_sqlite3_pselect(apr_pool_t *pool, apr_dbd_t *sql,
530251876Speter                               apr_dbd_results_t **results,
531251876Speter                               apr_dbd_prepared_t *statement, int seek,
532251876Speter                               const char **values)
533251876Speter{
534251876Speter    sqlite3_stmt *stmt = statement->stmt;
535251876Speter    int ret;
536251876Speter
537251876Speter    if (sql->trans && sql->trans->errnum) {
538251876Speter        return sql->trans->errnum;
539251876Speter    }
540251876Speter
541251876Speter    apr_dbd_mutex_lock();
542251876Speter
543251876Speter    ret = sqlite3_reset(stmt);
544251876Speter    if (ret == SQLITE_OK) {
545251876Speter        dbd_sqlite3_bind(statement, values);
546251876Speter
547251876Speter        ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
548251876Speter
549251876Speter        sqlite3_reset(stmt);
550251876Speter    }
551251876Speter
552251876Speter    apr_dbd_mutex_unlock();
553251876Speter
554251876Speter    if (TXN_NOTICE_ERRORS(sql->trans)) {
555251876Speter        sql->trans->errnum = ret;
556251876Speter    }
557251876Speter    return ret;
558251876Speter}
559251876Speter
560251876Speterstatic int dbd_sqlite3_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
561251876Speter                                apr_dbd_results_t **results,
562251876Speter                                apr_dbd_prepared_t *statement, int seek,
563251876Speter                                va_list args)
564251876Speter{
565251876Speter    const char **values;
566251876Speter    int i;
567251876Speter
568251876Speter    if (sql->trans && sql->trans->errnum) {
569251876Speter        return sql->trans->errnum;
570251876Speter    }
571251876Speter
572251876Speter    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
573251876Speter
574251876Speter    for (i = 0; i < statement->nvals; i++) {
575251876Speter        values[i] = va_arg(args, const char*);
576251876Speter    }
577251876Speter
578251876Speter    return dbd_sqlite3_pselect(pool, sql, results, statement, seek, values);
579251876Speter}
580251876Speter
581251876Speterstatic void dbd_sqlite3_bbind(apr_dbd_prepared_t * statement,
582251876Speter                              const void **values)
583251876Speter{
584251876Speter    sqlite3_stmt *stmt = statement->stmt;
585251876Speter    int i, j;
586251876Speter    apr_dbd_type_e type;
587251876Speter
588251876Speter    for (i = 0, j = 0; i < statement->nargs; i++, j++) {
589251876Speter        type = (values[j] == NULL ? APR_DBD_TYPE_NULL : statement->types[i]);
590251876Speter
591251876Speter        switch (type) {
592251876Speter        case APR_DBD_TYPE_TINY:
593251876Speter            sqlite3_bind_int(stmt, i + 1, *(char*)values[j]);
594251876Speter            break;
595251876Speter        case APR_DBD_TYPE_UTINY:
596251876Speter            sqlite3_bind_int(stmt, i + 1, *(unsigned char*)values[j]);
597251876Speter            break;
598251876Speter        case APR_DBD_TYPE_SHORT:
599251876Speter            sqlite3_bind_int(stmt, i + 1, *(short*)values[j]);
600251876Speter            break;
601251876Speter        case APR_DBD_TYPE_USHORT:
602251876Speter            sqlite3_bind_int(stmt, i + 1, *(unsigned short*)values[j]);
603251876Speter            break;
604251876Speter        case APR_DBD_TYPE_INT:
605251876Speter            sqlite3_bind_int(stmt, i + 1, *(int*)values[j]);
606251876Speter            break;
607251876Speter        case APR_DBD_TYPE_UINT:
608251876Speter            sqlite3_bind_int(stmt, i + 1, *(unsigned int*)values[j]);
609251876Speter            break;
610251876Speter        case APR_DBD_TYPE_LONG:
611251876Speter            sqlite3_bind_int64(stmt, i + 1, *(long*)values[j]);
612251876Speter            break;
613251876Speter        case APR_DBD_TYPE_ULONG:
614251876Speter            sqlite3_bind_int64(stmt, i + 1, *(unsigned long*)values[j]);
615251876Speter            break;
616251876Speter        case APR_DBD_TYPE_LONGLONG:
617251876Speter            sqlite3_bind_int64(stmt, i + 1, *(apr_int64_t*)values[j]);
618251876Speter            break;
619251876Speter        case APR_DBD_TYPE_ULONGLONG:
620251876Speter            sqlite3_bind_int64(stmt, i + 1, *(apr_uint64_t*)values[j]);
621251876Speter            break;
622251876Speter        case APR_DBD_TYPE_FLOAT:
623251876Speter            sqlite3_bind_double(stmt, i + 1, *(float*)values[j]);
624251876Speter            break;
625251876Speter        case APR_DBD_TYPE_DOUBLE:
626251876Speter            sqlite3_bind_double(stmt, i + 1, *(double*)values[j]);
627251876Speter            break;
628251876Speter        case APR_DBD_TYPE_STRING:
629251876Speter        case APR_DBD_TYPE_TEXT:
630251876Speter        case APR_DBD_TYPE_TIME:
631251876Speter        case APR_DBD_TYPE_DATE:
632251876Speter        case APR_DBD_TYPE_DATETIME:
633251876Speter        case APR_DBD_TYPE_TIMESTAMP:
634251876Speter        case APR_DBD_TYPE_ZTIMESTAMP:
635251876Speter            sqlite3_bind_text(stmt, i + 1, values[j], strlen(values[j]),
636251876Speter                              SQLITE_STATIC);
637251876Speter            break;
638251876Speter        case APR_DBD_TYPE_BLOB:
639251876Speter        case APR_DBD_TYPE_CLOB:
640251876Speter            {
641251876Speter            char *data = (char*)values[j];
642251876Speter            apr_size_t size = *(apr_size_t*)values[++j];
643251876Speter
644251876Speter            sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC);
645251876Speter
646251876Speter            /* skip table and column */
647251876Speter            j += 2;
648251876Speter            }
649251876Speter            break;
650251876Speter        case APR_DBD_TYPE_NULL:
651251876Speter        default:
652251876Speter            sqlite3_bind_null(stmt, i + 1);
653251876Speter            break;
654251876Speter        }
655251876Speter    }
656251876Speter
657251876Speter    return;
658251876Speter}
659251876Speter
660251876Speterstatic int dbd_sqlite3_pbquery(apr_pool_t * pool, apr_dbd_t * sql,
661251876Speter                               int *nrows, apr_dbd_prepared_t * statement,
662251876Speter                               const void **values)
663251876Speter{
664251876Speter    sqlite3_stmt *stmt = statement->stmt;
665251876Speter    int ret = -1;
666251876Speter
667251876Speter    if (sql->trans && sql->trans->errnum) {
668251876Speter        return sql->trans->errnum;
669251876Speter    }
670251876Speter
671251876Speter    apr_dbd_mutex_lock();
672251876Speter
673251876Speter    ret = sqlite3_reset(stmt);
674251876Speter    if (ret == SQLITE_OK) {
675251876Speter        dbd_sqlite3_bbind(statement, values);
676251876Speter
677251876Speter        ret = dbd_sqlite3_query_internal(sql, stmt, nrows);
678251876Speter
679251876Speter        sqlite3_reset(stmt);
680251876Speter    }
681251876Speter
682251876Speter    apr_dbd_mutex_unlock();
683251876Speter
684251876Speter    if (TXN_NOTICE_ERRORS(sql->trans)) {
685251876Speter        sql->trans->errnum = ret;
686251876Speter    }
687251876Speter    return ret;
688251876Speter}
689251876Speter
690251876Speterstatic int dbd_sqlite3_pvbquery(apr_pool_t * pool, apr_dbd_t * sql,
691251876Speter                                int *nrows, apr_dbd_prepared_t * statement,
692251876Speter                                va_list args)
693251876Speter{
694251876Speter    const void **values;
695251876Speter    int i;
696251876Speter
697251876Speter    if (sql->trans && sql->trans->errnum) {
698251876Speter        return sql->trans->errnum;
699251876Speter    }
700251876Speter
701251876Speter    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
702251876Speter
703251876Speter    for (i = 0; i < statement->nvals; i++) {
704251876Speter        values[i] = va_arg(args, const void*);
705251876Speter    }
706251876Speter
707251876Speter    return dbd_sqlite3_pbquery(pool, sql, nrows, statement, values);
708251876Speter}
709251876Speter
710251876Speterstatic int dbd_sqlite3_pbselect(apr_pool_t * pool, apr_dbd_t * sql,
711251876Speter                                apr_dbd_results_t ** results,
712251876Speter                                apr_dbd_prepared_t * statement,
713251876Speter                                int seek, const void **values)
714251876Speter{
715251876Speter    sqlite3_stmt *stmt = statement->stmt;
716251876Speter    int ret;
717251876Speter
718251876Speter    if (sql->trans && sql->trans->errnum) {
719251876Speter        return sql->trans->errnum;
720251876Speter    }
721251876Speter
722251876Speter    apr_dbd_mutex_lock();
723251876Speter
724251876Speter    ret = sqlite3_reset(stmt);
725251876Speter    if (ret == SQLITE_OK) {
726251876Speter        dbd_sqlite3_bbind(statement, values);
727251876Speter
728251876Speter        ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek);
729251876Speter
730251876Speter        sqlite3_reset(stmt);
731251876Speter    }
732251876Speter
733251876Speter    apr_dbd_mutex_unlock();
734251876Speter
735251876Speter    if (TXN_NOTICE_ERRORS(sql->trans)) {
736251876Speter        sql->trans->errnum = ret;
737251876Speter    }
738251876Speter    return ret;
739251876Speter}
740251876Speter
741251876Speterstatic int dbd_sqlite3_pvbselect(apr_pool_t * pool, apr_dbd_t * sql,
742251876Speter                                 apr_dbd_results_t ** results,
743251876Speter                                 apr_dbd_prepared_t * statement, int seek,
744251876Speter                                 va_list args)
745251876Speter{
746251876Speter    const void **values;
747251876Speter    int i;
748251876Speter
749251876Speter    if (sql->trans && sql->trans->errnum) {
750251876Speter        return sql->trans->errnum;
751251876Speter    }
752251876Speter
753251876Speter    values = apr_palloc(pool, sizeof(*values) * statement->nvals);
754251876Speter
755251876Speter    for (i = 0; i < statement->nvals; i++) {
756251876Speter        values[i] = va_arg(args, const void*);
757251876Speter    }
758251876Speter
759251876Speter    return dbd_sqlite3_pbselect(pool, sql, results, statement, seek, values);
760251876Speter}
761251876Speter
762251876Speterstatic int dbd_sqlite3_start_transaction(apr_pool_t *pool,
763251876Speter                                         apr_dbd_t *handle,
764251876Speter                                         apr_dbd_transaction_t **trans)
765251876Speter{
766251876Speter    int ret = 0;
767251876Speter    int nrows = 0;
768251876Speter
769251876Speter    ret = dbd_sqlite3_query(handle, &nrows, "BEGIN IMMEDIATE");
770251876Speter    if (!*trans) {
771251876Speter        *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
772251876Speter        (*trans)->handle = handle;
773251876Speter        handle->trans = *trans;
774251876Speter    }
775251876Speter
776251876Speter    return ret;
777251876Speter}
778251876Speter
779251876Speterstatic int dbd_sqlite3_end_transaction(apr_dbd_transaction_t *trans)
780251876Speter{
781251876Speter    int ret = -1; /* ending transaction that was never started is an error */
782251876Speter    int nrows = 0;
783251876Speter
784251876Speter    if (trans) {
785251876Speter        /* rollback on error or explicit rollback request */
786251876Speter        if (trans->errnum || TXN_DO_ROLLBACK(trans)) {
787251876Speter            trans->errnum = 0;
788251876Speter            ret = dbd_sqlite3_query(trans->handle, &nrows, "ROLLBACK");
789251876Speter        } else {
790251876Speter            ret = dbd_sqlite3_query(trans->handle, &nrows, "COMMIT");
791251876Speter        }
792251876Speter        trans->handle->trans = NULL;
793251876Speter    }
794251876Speter
795251876Speter    return ret;
796251876Speter}
797251876Speter
798251876Speterstatic int dbd_sqlite3_transaction_mode_get(apr_dbd_transaction_t *trans)
799251876Speter{
800251876Speter    if (!trans)
801251876Speter        return APR_DBD_TRANSACTION_COMMIT;
802251876Speter
803251876Speter    return trans->mode;
804251876Speter}
805251876Speter
806251876Speterstatic int dbd_sqlite3_transaction_mode_set(apr_dbd_transaction_t *trans,
807251876Speter                                            int mode)
808251876Speter{
809251876Speter    if (!trans)
810251876Speter        return APR_DBD_TRANSACTION_COMMIT;
811251876Speter
812251876Speter    return trans->mode = (mode & TXN_MODE_BITS);
813251876Speter}
814251876Speter
815251876Speterstatic apr_dbd_t *dbd_sqlite3_open(apr_pool_t *pool, const char *params,
816251876Speter                                   const char **error)
817251876Speter{
818251876Speter    apr_dbd_t *sql = NULL;
819251876Speter    sqlite3 *conn = NULL;
820251876Speter    int sqlres;
821251876Speter    if (!params)
822251876Speter        return NULL;
823251876Speter    sqlres = sqlite3_open(params, &conn);
824251876Speter    if (sqlres != SQLITE_OK) {
825251876Speter        if (error) {
826251876Speter            *error = apr_pstrdup(pool, sqlite3_errmsg(conn));
827251876Speter        }
828251876Speter        sqlite3_close(conn);
829251876Speter        return NULL;
830251876Speter    }
831251876Speter    /* should we register rand or power functions to the sqlite VM? */
832251876Speter    sql = apr_pcalloc(pool, sizeof(*sql));
833251876Speter    sql->conn = conn;
834251876Speter    sql->pool = pool;
835251876Speter    sql->trans = NULL;
836251876Speter
837251876Speter    return sql;
838251876Speter}
839251876Speter
840251876Speterstatic apr_status_t dbd_sqlite3_close(apr_dbd_t *handle)
841251876Speter{
842251876Speter    apr_dbd_prepared_t *prep = handle->prep;
843251876Speter
844251876Speter    /* finalize all prepared statements, or we'll get SQLITE_BUSY on close */
845251876Speter    while (prep) {
846251876Speter        sqlite3_finalize(prep->stmt);
847251876Speter        prep = prep->next;
848251876Speter    }
849251876Speter
850251876Speter    sqlite3_close(handle->conn);
851251876Speter    return APR_SUCCESS;
852251876Speter}
853251876Speter
854251876Speterstatic apr_status_t dbd_sqlite3_check_conn(apr_pool_t *pool,
855251876Speter                                           apr_dbd_t *handle)
856251876Speter{
857251876Speter    return (handle->conn != NULL) ? APR_SUCCESS : APR_EGENERAL;
858251876Speter}
859251876Speter
860251876Speterstatic int dbd_sqlite3_select_db(apr_pool_t *pool, apr_dbd_t *handle,
861251876Speter                                 const char *name)
862251876Speter{
863251876Speter    return APR_ENOTIMPL;
864251876Speter}
865251876Speter
866251876Speterstatic void *dbd_sqlite3_native(apr_dbd_t *handle)
867251876Speter{
868251876Speter    return handle->conn;
869251876Speter}
870251876Speter
871251876Speterstatic int dbd_sqlite3_num_cols(apr_dbd_results_t *res)
872251876Speter{
873251876Speter    return res->sz;
874251876Speter}
875251876Speter
876251876Speterstatic int dbd_sqlite3_num_tuples(apr_dbd_results_t *res)
877251876Speter{
878251876Speter    return res->tuples;
879251876Speter}
880251876Speter
881251876SpeterAPU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite3_driver = {
882251876Speter    "sqlite3",
883251876Speter    NULL,
884251876Speter    dbd_sqlite3_native,
885251876Speter    dbd_sqlite3_open,
886251876Speter    dbd_sqlite3_check_conn,
887251876Speter    dbd_sqlite3_close,
888251876Speter    dbd_sqlite3_select_db,
889251876Speter    dbd_sqlite3_start_transaction,
890251876Speter    dbd_sqlite3_end_transaction,
891251876Speter    dbd_sqlite3_query,
892251876Speter    dbd_sqlite3_select,
893251876Speter    dbd_sqlite3_num_cols,
894251876Speter    dbd_sqlite3_num_tuples,
895251876Speter    dbd_sqlite3_get_row,
896251876Speter    dbd_sqlite3_get_entry,
897251876Speter    dbd_sqlite3_error,
898251876Speter    dbd_sqlite3_escape,
899251876Speter    dbd_sqlite3_prepare,
900251876Speter    dbd_sqlite3_pvquery,
901251876Speter    dbd_sqlite3_pvselect,
902251876Speter    dbd_sqlite3_pquery,
903251876Speter    dbd_sqlite3_pselect,
904251876Speter    dbd_sqlite3_get_name,
905251876Speter    dbd_sqlite3_transaction_mode_get,
906251876Speter    dbd_sqlite3_transaction_mode_set,
907251876Speter    "?",
908251876Speter    dbd_sqlite3_pvbquery,
909251876Speter    dbd_sqlite3_pvbselect,
910251876Speter    dbd_sqlite3_pbquery,
911251876Speter    dbd_sqlite3_pbselect,
912251876Speter    dbd_sqlite3_datum_get
913251876Speter};
914251876Speter#endif
915