~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr-util/dbd/apr_dbd_sqlite3.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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_SQLITE3
 
20
 
 
21
#include <ctype.h>
 
22
#include <stdlib.h>
 
23
 
 
24
#include <sqlite3.h>
 
25
 
 
26
#include "apr_strings.h"
 
27
#include "apr_time.h"
 
28
 
 
29
#include "apr_dbd_internal.h"
 
30
 
 
31
#define MAX_RETRY_COUNT 15
 
32
#define MAX_RETRY_SLEEP 100000
 
33
 
 
34
struct apr_dbd_transaction_t {
 
35
    int errnum;
 
36
    apr_dbd_t *handle;
 
37
};
 
38
 
 
39
struct apr_dbd_t {
 
40
    sqlite3 *conn;
 
41
    apr_dbd_transaction_t *trans;
 
42
    apr_thread_mutex_t *mutex;
 
43
    apr_pool_t *pool;
 
44
};
 
45
 
 
46
typedef struct {
 
47
    char *name;
 
48
    char *value;
 
49
    int size;
 
50
    int type;
 
51
} apr_dbd_column_t;
 
52
 
 
53
struct apr_dbd_row_t {
 
54
    apr_dbd_results_t *res;
 
55
    apr_dbd_column_t **columns;
 
56
    apr_dbd_row_t *next_row;
 
57
    int columnCount;
 
58
    int rownum;
 
59
};
 
60
 
 
61
struct apr_dbd_results_t {
 
62
    int random;
 
63
    sqlite3 *handle;
 
64
    sqlite3_stmt *stmt;
 
65
    apr_dbd_row_t *next_row;
 
66
    size_t sz;
 
67
    int tuples;
 
68
    char **col_names;
 
69
};
 
70
 
 
71
struct apr_dbd_prepared_t {
 
72
    const char *name;
 
73
    int prepared;
 
74
};
 
75
 
 
76
#define dbd_sqlite3_is_success(x) (((x) == SQLITE_DONE ) \
 
77
                || ((x) == SQLITE_OK ))
 
78
 
 
79
static int dbd_sqlite3_select(apr_pool_t * pool, apr_dbd_t * sql, apr_dbd_results_t ** results, const char *query, int seek)
 
80
{
 
81
    sqlite3_stmt *stmt = NULL;
 
82
    const char *tail = NULL;
 
83
    int i, ret, retry_count = 0;
 
84
    size_t num_tuples = 0;
 
85
    int increment = 0;
 
86
    apr_dbd_row_t *row = NULL;
 
87
    apr_dbd_row_t *lastrow = NULL;
 
88
    apr_dbd_column_t *column;
 
89
 
 
90
    char *hold = NULL;
 
91
 
 
92
    if (sql->trans && sql->trans->errnum) {
 
93
        return sql->trans->errnum;
 
94
    }
 
95
 
 
96
    apr_thread_mutex_lock(sql->mutex);
 
97
 
 
98
    ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail);
 
99
    if (!dbd_sqlite3_is_success(ret)) {
 
100
        apr_thread_mutex_unlock(sql->mutex);
 
101
        return ret;
 
102
    } else {
 
103
        int column_count;
 
104
        column_count = sqlite3_column_count(stmt);
 
105
        if (!*results) {
 
106
            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
 
107
        }
 
108
        (*results)->stmt = stmt;
 
109
        (*results)->sz = column_count;
 
110
        (*results)->random = seek;
 
111
        (*results)->next_row = 0;
 
112
        (*results)->tuples = 0;
 
113
        (*results)->col_names = apr_pcalloc(pool,
 
114
                                            column_count * sizeof(char *));
 
115
        do {
 
116
            ret = sqlite3_step((*results)->stmt);
 
117
            if (ret == SQLITE_BUSY) {
 
118
                if (retry_count++ > MAX_RETRY_COUNT) {
 
119
                    ret = SQLITE_ERROR;
 
120
                } else {
 
121
                    apr_thread_mutex_unlock(sql->mutex);
 
122
                    apr_sleep(MAX_RETRY_SLEEP);
 
123
                    apr_thread_mutex_lock(sql->mutex);
 
124
                }
 
125
            } else if (ret == SQLITE_ROW) {
 
126
                int length;
 
127
                apr_dbd_column_t *col;
 
128
                row = apr_palloc(pool, sizeof(apr_dbd_row_t));
 
129
                row->res = *results;
 
130
                row->res->stmt = (*results)->stmt;
 
131
                increment = sizeof(apr_dbd_column_t *);
 
132
                length = increment * (*results)->sz;
 
133
                row->columns = apr_palloc(pool, length);
 
134
                row->columnCount = column_count;
 
135
                for (i = 0; i < (*results)->sz; i++) {
 
136
                    column = apr_palloc(pool, sizeof(apr_dbd_column_t));
 
137
                    row->columns[i] = column;
 
138
                    /* copy column name once only */
 
139
                    if ((*results)->col_names[i] == NULL) {
 
140
                      (*results)->col_names[i] =
 
141
                          apr_pstrdup(pool,
 
142
                                      sqlite3_column_name((*results)->stmt, i));
 
143
                    }
 
144
                    column->name = (*results)->col_names[i];
 
145
                    column->size = sqlite3_column_bytes((*results)->stmt, i);
 
146
                    column->type = sqlite3_column_type((*results)->stmt, i);
 
147
                    column->value = NULL;
 
148
                    switch (column->type) {
 
149
                    case SQLITE_FLOAT:
 
150
                    case SQLITE_INTEGER:
 
151
                    case SQLITE_TEXT:
 
152
                        hold = NULL;
 
153
                        hold = (char *) sqlite3_column_text((*results)->stmt, i);
 
154
                        if (hold) {
 
155
                            column->value = apr_palloc(pool, column->size + 1);
 
156
                            strncpy(column->value, hold, column->size + 1);
 
157
                        }
 
158
                        break;
 
159
                    case SQLITE_BLOB:
 
160
                        break;
 
161
                    case SQLITE_NULL:
 
162
                        break;
 
163
                    }
 
164
                    col = row->columns[i];
 
165
                }
 
166
                row->rownum = num_tuples++;
 
167
                row->next_row = 0;
 
168
                (*results)->tuples = num_tuples;
 
169
                if ((*results)->next_row == 0) {
 
170
                    (*results)->next_row = row;
 
171
                }
 
172
                if (lastrow != 0) {
 
173
                    lastrow->next_row = row;
 
174
                }
 
175
                lastrow = row;
 
176
            } else if (ret == SQLITE_DONE) {
 
177
                ret = SQLITE_OK;
 
178
            }
 
179
        } while (ret == SQLITE_ROW || ret == SQLITE_BUSY);
 
180
    }
 
181
    ret = sqlite3_finalize(stmt);
 
182
    apr_thread_mutex_unlock(sql->mutex);
 
183
 
 
184
    if (sql->trans) {
 
185
        sql->trans->errnum = ret;
 
186
    }
 
187
    return ret;
 
188
}
 
189
 
 
190
static int dbd_sqlite3_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
 
191
                               apr_dbd_row_t **rowp, int rownum)
 
192
{
 
193
    int i = 0;
 
194
 
 
195
    if (rownum == -1) {
 
196
        *rowp = res->next_row;
 
197
        if (*rowp == 0)
 
198
            return -1;
 
199
        res->next_row = (*rowp)->next_row;
 
200
        return 0;
 
201
    }
 
202
    if (rownum > res->tuples) {
 
203
        return -1;
 
204
    }
 
205
    rownum--;
 
206
    *rowp = res->next_row;
 
207
    for (; *rowp != 0; i++, *rowp = (*rowp)->next_row) {
 
208
        if (i == rownum) {
 
209
            return 0;
 
210
        }
 
211
    }
 
212
 
 
213
    return -1;
 
214
 
 
215
}
 
216
 
 
217
static const char *dbd_sqlite3_get_entry(const apr_dbd_row_t *row, int n)
 
218
{
 
219
    apr_dbd_column_t *column;
 
220
    const char *value;
 
221
    if ((n < 0) || (n >= row->columnCount)) {
 
222
        return NULL;
 
223
    }
 
224
    column = row->columns[n];
 
225
    value = column->value;
 
226
    return value;
 
227
}
 
228
 
 
229
static const char *dbd_sqlite3_error(apr_dbd_t *sql, int n)
 
230
{
 
231
    return sqlite3_errmsg(sql->conn);
 
232
}
 
233
 
 
234
static int dbd_sqlite3_query(apr_dbd_t *sql, int *nrows, const char *query)
 
235
{
 
236
    sqlite3_stmt *stmt = NULL;
 
237
    const char *tail = NULL;
 
238
    int ret = -1, length = 0;
 
239
 
 
240
    if (sql->trans && sql->trans->errnum) {
 
241
        return sql->trans->errnum;
 
242
    }
 
243
 
 
244
    length = strlen(query);
 
245
    apr_thread_mutex_lock(sql->mutex);
 
246
 
 
247
    do {
 
248
        ret = sqlite3_prepare(sql->conn, query, length, &stmt, &tail);
 
249
        if (ret != SQLITE_OK) {
 
250
            sqlite3_finalize(stmt);
 
251
            break;
 
252
        }
 
253
        ret = sqlite3_step(stmt);
 
254
        *nrows = sqlite3_changes(sql->conn);
 
255
        sqlite3_finalize(stmt);
 
256
        length -= (tail - query);
 
257
        query = tail;
 
258
    } while (length > 0);
 
259
 
 
260
    if (dbd_sqlite3_is_success(ret)) {
 
261
        ret =  0;
 
262
    }
 
263
    apr_thread_mutex_unlock(sql->mutex);
 
264
    if (sql->trans) {
 
265
        sql->trans->errnum = ret;
 
266
    }
 
267
    return ret;
 
268
}
 
269
 
 
270
static const char *dbd_sqlite3_escape(apr_pool_t *pool, const char *arg,
 
271
                                      apr_dbd_t *sql)
 
272
{
 
273
    char *ret = sqlite3_mprintf("%q", arg);
 
274
    apr_pool_cleanup_register(pool, ret, (void *) sqlite3_free,
 
275
                              apr_pool_cleanup_null);
 
276
    return ret;
 
277
}
 
278
 
 
279
static int dbd_sqlite3_prepare(apr_pool_t *pool, apr_dbd_t *sql,
 
280
                               const char *query, const char *label,
 
281
                               apr_dbd_prepared_t **statement)
 
282
{
 
283
    return APR_ENOTIMPL;
 
284
}
 
285
 
 
286
static int dbd_sqlite3_pquery(apr_pool_t *pool, apr_dbd_t *sql,
 
287
                              int *nrows, apr_dbd_prepared_t *statement,
 
288
                              int nargs, const char **values)
 
289
{
 
290
    return APR_ENOTIMPL;
 
291
}
 
292
 
 
293
static int dbd_sqlite3_pvquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,
 
294
                               apr_dbd_prepared_t *statement, va_list args)
 
295
{
 
296
    return APR_ENOTIMPL;
 
297
}
 
298
 
 
299
static int dbd_sqlite3_pselect(apr_pool_t *pool, apr_dbd_t *sql,
 
300
                               apr_dbd_results_t **results,
 
301
                               apr_dbd_prepared_t *statement, int seek,
 
302
                               int nargs, const char **values)
 
303
{
 
304
    return APR_ENOTIMPL;
 
305
}
 
306
 
 
307
static int dbd_sqlite3_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
 
308
                                apr_dbd_results_t **results,
 
309
                                apr_dbd_prepared_t *statement, int seek,
 
310
                                va_list args)
 
311
{
 
312
    return APR_ENOTIMPL;
 
313
}
 
314
 
 
315
static int dbd_sqlite3_start_transaction(apr_pool_t *pool,
 
316
                                         apr_dbd_t *handle,
 
317
                                         apr_dbd_transaction_t **trans)
 
318
{
 
319
    int ret = 0;
 
320
    int nrows = 0;
 
321
 
 
322
    ret = dbd_sqlite3_query(handle, &nrows, "BEGIN TRANSACTION;");
 
323
    if (!*trans) {
 
324
        *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
 
325
        (*trans)->handle = handle;
 
326
        handle->trans = *trans;
 
327
    }
 
328
 
 
329
    return ret;
 
330
}
 
331
 
 
332
static int dbd_sqlite3_end_transaction(apr_dbd_transaction_t *trans)
 
333
{
 
334
    int ret = 0;
 
335
    int nrows = 0;
 
336
 
 
337
    if (trans) {
 
338
        ret = dbd_sqlite3_query(trans->handle, &nrows, "END TRANSACTION;");
 
339
        if (trans->errnum) {
 
340
            trans->errnum = 0;
 
341
            ret = dbd_sqlite3_query(trans->handle, &nrows, "ROLLBACK;");
 
342
        } else {
 
343
            ret = dbd_sqlite3_query(trans->handle, &nrows, "COMMIT;");
 
344
        }
 
345
        trans->handle->trans = NULL;
 
346
    }
 
347
 
 
348
    return ret;
 
349
}
 
350
 
 
351
static apr_dbd_t *dbd_sqlite3_open(apr_pool_t *pool, const char *params)
 
352
{
 
353
    apr_dbd_t *sql = NULL;
 
354
    sqlite3 *conn = NULL;
 
355
    apr_status_t res;
 
356
    int sqlres;
 
357
    if (!params)
 
358
        return NULL;
 
359
    sqlres = sqlite3_open(params, &conn);
 
360
    if (sqlres != SQLITE_OK) {
 
361
        sqlite3_close(conn);
 
362
        return NULL;
 
363
    }
 
364
    /* should we register rand or power functions to the sqlite VM? */
 
365
    sql = apr_pcalloc(pool, sizeof(*sql));
 
366
    sql->conn = conn;
 
367
    sql->pool = pool;
 
368
    sql->trans = NULL;
 
369
    /* Create a mutex */
 
370
    res = apr_thread_mutex_create(&sql->mutex, APR_THREAD_MUTEX_DEFAULT,
 
371
                                  pool);
 
372
    if (res != APR_SUCCESS) {
 
373
        return NULL;
 
374
    }
 
375
 
 
376
    return sql;
 
377
}
 
378
 
 
379
static apr_status_t dbd_sqlite3_close(apr_dbd_t *handle)
 
380
{
 
381
    sqlite3_close(handle->conn);
 
382
    apr_thread_mutex_destroy(handle->mutex);
 
383
    return APR_SUCCESS;
 
384
}
 
385
 
 
386
static apr_status_t dbd_sqlite3_check_conn(apr_pool_t *pool,
 
387
                                           apr_dbd_t *handle)
 
388
{
 
389
    return (handle->conn != NULL) ? APR_SUCCESS : APR_EGENERAL;
 
390
}
 
391
 
 
392
static int dbd_sqlite3_select_db(apr_pool_t *pool, apr_dbd_t *handle,
 
393
                                 const char *name)
 
394
{
 
395
    return APR_ENOTIMPL;
 
396
}
 
397
 
 
398
static void *dbd_sqlite3_native(apr_dbd_t *handle)
 
399
{
 
400
    return handle->conn;
 
401
}
 
402
 
 
403
static int dbd_sqlite3_num_cols(apr_dbd_results_t *res)
 
404
{
 
405
    return res->sz;
 
406
}
 
407
 
 
408
static int dbd_sqlite3_num_tuples(apr_dbd_results_t *res)
 
409
{
 
410
    return res->tuples;
 
411
}
 
412
 
 
413
APU_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite3_driver = {
 
414
    "sqlite3",
 
415
    NULL,
 
416
    dbd_sqlite3_native,
 
417
    dbd_sqlite3_open,
 
418
    dbd_sqlite3_check_conn,
 
419
    dbd_sqlite3_close,
 
420
    dbd_sqlite3_select_db,
 
421
    dbd_sqlite3_start_transaction,
 
422
    dbd_sqlite3_end_transaction,
 
423
    dbd_sqlite3_query,
 
424
    dbd_sqlite3_select,
 
425
    dbd_sqlite3_num_cols,
 
426
    dbd_sqlite3_num_tuples,
 
427
    dbd_sqlite3_get_row,
 
428
    dbd_sqlite3_get_entry,
 
429
    dbd_sqlite3_error,
 
430
    dbd_sqlite3_escape,
 
431
    dbd_sqlite3_prepare,
 
432
    dbd_sqlite3_pvquery,
 
433
    dbd_sqlite3_pvselect,
 
434
    dbd_sqlite3_pquery,
 
435
    dbd_sqlite3_pselect,
 
436
};
 
437
#endif