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

« back to all changes in this revision

Viewing changes to srclib/apr-util/dbd/apr_dbd_sqlite2.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_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
 
 
29
#include "apr_dbd_internal.h"
 
30
 
 
31
struct apr_dbd_transaction_t {
 
32
    int errnum;
 
33
    apr_dbd_t *handle;
 
34
};
 
35
 
 
36
struct apr_dbd_t {
 
37
    sqlite *conn;
 
38
    char *errmsg;
 
39
    apr_dbd_transaction_t *trans;
 
40
};
 
41
 
 
42
struct apr_dbd_results_t {
 
43
    int random;
 
44
    sqlite *handle;
 
45
    char **res;
 
46
    size_t ntuples;
 
47
    size_t sz;
 
48
    size_t index;
 
49
};
 
50
 
 
51
struct apr_dbd_row_t {
 
52
    int n;
 
53
    char **data;
 
54
    apr_dbd_results_t *res;
 
55
};
 
56
 
 
57
struct apr_dbd_prepared_t {
 
58
    const char *name;
 
59
    int prepared;
 
60
};
 
61
 
 
62
#define FREE_ERROR_MSG(dbd) \
 
63
        do { \
 
64
                if(dbd && dbd->errmsg) { \
 
65
                        free(dbd->errmsg); \
 
66
                        dbd->errmsg = NULL; \
 
67
                } \
 
68
        } while(0);
 
69
 
 
70
 
 
71
static int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql,
 
72
                             apr_dbd_results_t ** results, const char *query,
 
73
                             int seek)
 
74
{
 
75
    char **result;
 
76
    int ret = 0;
 
77
    int tuples = 0;
 
78
    int fields = 0;
 
79
 
 
80
    if (sql->trans && sql->trans->errnum) {
 
81
        return sql->trans->errnum;
 
82
    }
 
83
 
 
84
    FREE_ERROR_MSG(sql);
 
85
 
 
86
    ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
 
87
                          &sql->errmsg);
 
88
 
 
89
    if (ret == SQLITE_OK) {
 
90
        if (!*results) {
 
91
            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
 
92
        }
 
93
 
 
94
        (*results)->res = result;
 
95
        if (seek) {
 
96
            (*results)->ntuples = tuples;
 
97
        }
 
98
        else {
 
99
            (*results)->ntuples = -1;
 
100
        }
 
101
        (*results)->sz = fields;
 
102
        (*results)->random = seek;
 
103
 
 
104
        if (tuples > 0)
 
105
            apr_pool_cleanup_register(pool, result, (void *) free,
 
106
                                      apr_pool_cleanup_null);
 
107
 
 
108
        ret = 0;
 
109
    }
 
110
    else {
 
111
        sql->trans->errnum = ret;
 
112
    }
 
113
 
 
114
    return ret;
 
115
}
 
116
 
 
117
static int dbd_sqlite_get_row(apr_pool_t * pool, apr_dbd_results_t * res,
 
118
                              apr_dbd_row_t ** rowp, int rownum)
 
119
{
 
120
    apr_dbd_row_t *row = *rowp;
 
121
    int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
 
122
 
 
123
    if (row == NULL) {
 
124
        row = apr_palloc(pool, sizeof(apr_dbd_row_t));
 
125
        *rowp = row;
 
126
        row->res = res;
 
127
        row->n = sequential ? 0 : rownum - 1;
 
128
    }
 
129
    else {
 
130
        if (sequential) {
 
131
            ++row->n;
 
132
        }
 
133
        else {
 
134
            row->n = rownum - 1;
 
135
        }
 
136
    }
 
137
 
 
138
    if (row->n >= res->ntuples) {
 
139
        *rowp = NULL;
 
140
        apr_pool_cleanup_kill(pool, res->res, (void *) free);
 
141
        res->res = NULL;
 
142
        return -1;
 
143
    }
 
144
 
 
145
    /* Pointer magic explanation:
 
146
     *      The sqlite result is an array such that the first res->sz elements are 
 
147
     *      the column names and each tuple follows afterwards 
 
148
     *      ex: (from the sqlite2 documentation)
 
149
     SELECT employee_name, login, host FROM users WHERE login LIKE *        'd%';
 
150
 
 
151
     nrow = 2
 
152
     ncolumn = 3
 
153
     result[0] = "employee_name"
 
154
     result[1] = "login"
 
155
     result[2] = "host"
 
156
     result[3] = "dummy"
 
157
     result[4] = "No such user"
 
158
     result[5] = 0
 
159
     result[6] = "D. Richard Hipp"
 
160
     result[7] = "drh"
 
161
     result[8] = "zadok"
 
162
     */
 
163
 
 
164
    row->data = res->res + res->sz + (res->sz * row->n);
 
165
 
 
166
    return 0;
 
167
}
 
168
 
 
169
static const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
 
170
{
 
171
    if ((n < 0) || (n >= row->res->sz)) {
 
172
      return NULL;
 
173
    }
 
174
 
 
175
    return row->data[n];
 
176
}
 
177
 
 
178
static const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
 
179
{
 
180
    return sql->errmsg;
 
181
}
 
182
 
 
183
static int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
 
184
{
 
185
    char **result;
 
186
    int ret;
 
187
    int tuples = 0;
 
188
    int fields = 0;
 
189
 
 
190
    if (sql->trans && sql->trans->errnum) {
 
191
        return sql->trans->errnum;
 
192
    }
 
193
 
 
194
    FREE_ERROR_MSG(sql);
 
195
 
 
196
    ret =
 
197
        sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
 
198
                         &sql->errmsg);
 
199
    if (ret == SQLITE_OK) {
 
200
        *nrows = sqlite_changes(sql->conn);
 
201
 
 
202
        if (tuples > 0)
 
203
            free(result);
 
204
 
 
205
        ret = 0;
 
206
    }
 
207
 
 
208
    if (sql->trans) {
 
209
        sql->trans->errnum = ret;
 
210
    }
 
211
 
 
212
    return ret;
 
213
}
 
214
 
 
215
static const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
 
216
                                     apr_dbd_t * sql)
 
217
{
 
218
    char *ret = sqlite_mprintf("%q", arg);
 
219
    apr_pool_cleanup_register(pool, ret, (void *) sqlite_freemem,
 
220
                              apr_pool_cleanup_null);
 
221
    return ret;
 
222
}
 
223
 
 
224
static int dbd_sqlite_prepare(apr_pool_t * pool, apr_dbd_t * sql,
 
225
                              const char *query, const char *label,
 
226
                              apr_dbd_prepared_t ** statement)
 
227
{
 
228
    return APR_ENOTIMPL;
 
229
}
 
230
 
 
231
static int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql,
 
232
                             int *nrows, apr_dbd_prepared_t * statement,
 
233
                             int nargs, const char **values)
 
234
{
 
235
    return APR_ENOTIMPL;
 
236
}
 
237
 
 
238
static int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
 
239
                              int *nrows, apr_dbd_prepared_t * statement,
 
240
                              va_list args)
 
241
{
 
242
    return APR_ENOTIMPL;
 
243
}
 
244
 
 
245
static int dbd_sqlite_pselect(apr_pool_t * pool, apr_dbd_t * sql,
 
246
                              apr_dbd_results_t ** results,
 
247
                              apr_dbd_prepared_t * statement,
 
248
                              int seek, int nargs, const char **values)
 
249
{
 
250
    return APR_ENOTIMPL;
 
251
}
 
252
 
 
253
static int dbd_sqlite_pvselect(apr_pool_t * pool, apr_dbd_t * sql,
 
254
                               apr_dbd_results_t ** results,
 
255
                               apr_dbd_prepared_t * statement, int seek,
 
256
                               va_list args)
 
257
{
 
258
    return APR_ENOTIMPL;
 
259
}
 
260
 
 
261
static int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
 
262
                                        apr_dbd_transaction_t ** trans)
 
263
{
 
264
    int ret, rows;
 
265
 
 
266
    ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION");
 
267
    if (ret == 0) {
 
268
        if (!*trans) {
 
269
            *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
 
270
        }
 
271
        (*trans)->handle = handle;
 
272
        handle->trans = *trans;
 
273
    }
 
274
    else {
 
275
        ret = -1;
 
276
    }
 
277
    return ret;
 
278
}
 
279
 
 
280
static int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
 
281
{
 
282
    int rows;
 
283
    int ret = -1;               /* no transaction is an error cond */
 
284
 
 
285
    if (trans) {
 
286
        if (trans->errnum) {
 
287
            trans->errnum = 0;
 
288
            ret =
 
289
                dbd_sqlite_query(trans->handle, &rows,
 
290
                                 "ROLLBACK TRANSACTION");
 
291
        }
 
292
        else {
 
293
            ret =
 
294
                dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
 
295
        }
 
296
        trans->handle->trans = NULL;
 
297
    }
 
298
 
 
299
    return ret;
 
300
}
 
301
 
 
302
static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_)
 
303
{
 
304
    apr_dbd_t *sql;
 
305
    sqlite *conn = NULL;
 
306
    char *filename, *perm;
 
307
    int iperms = 600;
 
308
    char* params = apr_pstrdup(pool, params_);
 
309
    /* params = "[filename]:[permissions]"
 
310
     *    example: "shopping.db:600"
 
311
     */
 
312
 
 
313
    perm = strstr(params, ":");
 
314
    if (perm) {
 
315
        *(perm++) = '\x00';     /* split the filename and permissions */
 
316
 
 
317
        if (strlen(perm) > 0)
 
318
            iperms = atoi(perm);
 
319
    }
 
320
 
 
321
    conn = sqlite_open(params, iperms, NULL);
 
322
 
 
323
    sql = apr_pcalloc(pool, sizeof(*sql));
 
324
    sql->conn = conn;
 
325
 
 
326
    return sql;
 
327
}
 
328
 
 
329
static apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
 
330
{
 
331
    if (handle->conn) {
 
332
        sqlite_close(handle->conn);
 
333
        handle->conn = NULL;
 
334
    }
 
335
    return APR_SUCCESS;
 
336
}
 
337
 
 
338
static apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
 
339
                                          apr_dbd_t * handle)
 
340
{
 
341
    if (handle->conn == NULL)
 
342
        return -1;
 
343
    return APR_SUCCESS;
 
344
}
 
345
 
 
346
static int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
 
347
                                const char *name)
 
348
{
 
349
    return APR_ENOTIMPL;
 
350
}
 
351
 
 
352
static void *dbd_sqlite_native(apr_dbd_t * handle)
 
353
{
 
354
    return handle->conn;
 
355
}
 
356
 
 
357
static int dbd_sqlite_num_cols(apr_dbd_results_t * res)
 
358
{
 
359
    return res->sz;
 
360
}
 
361
 
 
362
static int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
 
363
{
 
364
    return res->ntuples;
 
365
}
 
366
 
 
367
APU_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = {
 
368
    "sqlite2",
 
369
    NULL,
 
370
    dbd_sqlite_native,
 
371
    dbd_sqlite_open,
 
372
    dbd_sqlite_check_conn,
 
373
    dbd_sqlite_close,
 
374
    dbd_sqlite_select_db,
 
375
    dbd_sqlite_start_transaction,
 
376
    dbd_sqlite_end_transaction,
 
377
    dbd_sqlite_query,
 
378
    dbd_sqlite_select,
 
379
    dbd_sqlite_num_cols,
 
380
    dbd_sqlite_num_tuples,
 
381
    dbd_sqlite_get_row,
 
382
    dbd_sqlite_get_entry,
 
383
    dbd_sqlite_error,
 
384
    dbd_sqlite_escape,
 
385
    dbd_sqlite_prepare,
 
386
    dbd_sqlite_pvquery,
 
387
    dbd_sqlite_pvselect,
 
388
    dbd_sqlite_pquery,
 
389
    dbd_sqlite_pselect,
 
390
};
 
391
#endif