Apache HTTPD
apr_dbd.c
Go to the documentation of this file.
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 <ctype.h>
18#include <stdio.h>
19
20#include "apu_config.h"
21#include "apu.h"
22
23#include "apr_pools.h"
24#include "apr_dso.h"
25#include "apr_strings.h"
26#include "apr_hash.h"
27#include "apr_thread_mutex.h"
28#include "apr_lib.h"
29#include "apr_atomic.h"
30
31#include "apu_internal.h"
32#include "apr_dbd_internal.h"
33#include "apr_dbd.h"
34#include "apu_version.h"
35
38
39#define CLEANUP_CAST (apr_status_t (*)(void*))
40
41#if APR_HAS_THREADS
42/* deprecated, but required for existing providers. Existing and new
43 * providers should be refactored to use a provider-specific mutex so
44 * that different providers do not block one another.
45 * In APR 1.3 this is no longer used for dso module loading, and
46 * apu_dso_mutex_[un]lock is used instead.
47 * In APR 2.0 this should become entirely local to libaprutil-2.so and
48 * no longer be exported.
49 */
50static apr_thread_mutex_t* mutex = NULL;
52{
53 return apr_thread_mutex_lock(mutex);
54}
56{
57 return apr_thread_mutex_unlock(mutex);
58}
59#else
64 return APR_SUCCESS;
65}
66#endif
67
68#if !APU_DSO_BUILD
69#define DRIVER_LOAD(name,driver,pool) \
70 { \
71 extern const apr_dbd_driver_t driver; \
72 apr_hash_set(drivers,name,APR_HASH_KEY_STRING,&driver); \
73 if (driver.init) { \
74 driver.init(pool); \
75 } \
76 }
77#endif
78
79static apr_status_t apr_dbd_term(void *ptr)
80{
81 /* set drivers to NULL so init can work again */
82 drivers = NULL;
83
84 /* Everything else we need is handled by cleanups registered
85 * when we created mutexes and loaded DSOs
86 */
87 return APR_SUCCESS;
88}
89
91{
94
96 apr_atomic_set32(&initialised, 1); /* prevent wrap-around */
97
98 while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */
99 ;
100
101 return APR_SUCCESS;
102 }
103
104 /* Top level pool scope, need process-scope lifetime */
106 parent && parent != pool;
108 pool = parent;
109#if APU_DSO_BUILD
110 /* deprecate in 2.0 - permit implicit initialization */
112#endif
113
115
116#if APR_HAS_THREADS
118 /* This already registers a pool cleanup */
119#endif
120
121#if !APU_DSO_BUILD
122
123 /* Load statically-linked drivers: */
124#if APU_HAVE_MYSQL
126#endif
127#if APU_HAVE_PGSQL
129#endif
130#if APU_HAVE_SQLITE3
132#endif
133#if APU_HAVE_SQLITE2
135#endif
136#if APU_HAVE_ORACLE
138#endif
139#if APU_HAVE_ODBC
141#endif
142#if APU_HAVE_SOME_OTHER_BACKEND
144#endif
145#endif /* APU_DSO_BUILD */
146
149
151
152 return ret;
153}
154
156 const apr_dbd_driver_t **driver)
157{
158#if APU_DSO_BUILD
159 char modname[32];
160 char symname[34];
162#endif
163 apr_status_t rv;
164
165#if APU_DSO_BUILD
166 rv = apu_dso_mutex_lock();
167 if (rv) {
168 return rv;
169 }
170#endif
172 if (*driver) {
173#if APU_DSO_BUILD
175#endif
176 return APR_SUCCESS;
177 }
178
179#if APU_DSO_BUILD
180 /* The driver DSO must have exactly the same lifetime as the
181 * drivers hash table; ignore the passed-in pool */
183
184#if defined(NETWARE)
185 apr_snprintf(modname, sizeof(modname), "dbd%s.nlm", name);
186#elif defined(WIN32) || defined(__CYGWIN__)
188 "apr_dbd_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", name);
189#else
191 "apr_dbd_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", name);
192#endif
193 apr_snprintf(symname, sizeof(symname), "apr_dbd_%s_driver", name);
194 rv = apu_dso_load(NULL, &symbol, modname, symname, pool);
195 if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
196 *driver = symbol;
199 rv = APR_SUCCESS;
200 if ((*driver)->init) {
201 (*driver)->init(pool);
202 }
203 }
205
206#else /* not builtin and !APU_DSO_BUILD => not implemented */
207 rv = APR_ENOTIMPL;
208#endif
209
210 return rv;
211}
212
214 apr_pool_t *pool, const char *params,
216 const char **error)
217{
218 apr_status_t rv;
220 if (*handle == NULL) {
221 return APR_EGENERAL;
222 }
224 if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) {
225 /* XXX: rv is APR error code, but apr_dbd_error() takes int! */
226 if (error) {
228 }
230 return APR_EGENERAL;
231 }
232 return APR_SUCCESS;
233}
234
236 apr_pool_t *pool, const char *params,
238{
240}
241
245{
247 if (*trans) {
251 }
252 return ret;
253}
254
258{
261}
262
265{
267}
268
271 int mode)
272{
274}
275
278{
279 return driver->close(handle);
280}
281
283{
284 return driver->name;
285}
286
292
296{
297 return driver->check_conn(pool, handle);
298}
299
302 apr_dbd_t *handle, const char *name)
303{
305}
306
309 int *nrows, const char *statement)
310{
312}
313
317 const char *statement, int random)
318{
320}
321
324{
325 return driver->num_cols(res);
326}
327
330{
331 return driver->num_tuples(res);
332}
333
337 int rownum)
338{
339 return driver->get_row(pool,res,row,rownum);
340}
341
343 apr_dbd_row_t *row, int col)
344{
345 return driver->get_entry(row,col);
346}
347
350{
351 return driver->get_name(res,col);
352}
353
355 apr_dbd_t *handle, int errnum)
356{
357 return driver->error(handle,errnum);
358}
359
361 apr_pool_t *pool, const char *string,
363{
364 return driver->escape(pool,string,handle);
365}
366
369 apr_dbd_t *handle, const char *query,
370 const char *label,
372{
373 size_t qlen;
374 int i, nargs = 0, nvals = 0;
375 char *p, *pq;
376 const char *q;
378
379 if (!driver->pformat) {
380 return APR_ENOTIMPL;
381 }
382
383 /* find the number of parameters in the query */
384 for (q = query; *q; q++) {
385 if (q[0] == '%') {
386 if (apr_isalpha(q[1])) {
387 nargs++;
388 } else if (q[1] == '%') {
389 q++;
390 }
391 }
392 }
393 nvals = nargs;
394
395 qlen = strlen(query) +
396 nargs * (strlen(driver->pformat) + sizeof(nargs) * 3 + 2) + 1;
398 t = apr_pcalloc(pool, sizeof(*t) * nargs);
399
400 for (p = pq, q = query, i = 0; *q; q++) {
401 if (q[0] == '%') {
402 if (apr_isalpha(q[1])) {
403 switch (q[1]) {
404 case 'd': t[i] = APR_DBD_TYPE_INT; break;
405 case 'u': t[i] = APR_DBD_TYPE_UINT; break;
406 case 'f': t[i] = APR_DBD_TYPE_FLOAT; break;
407 case 'h':
408 switch (q[2]) {
409 case 'h':
410 switch (q[3]){
411 case 'd': t[i] = APR_DBD_TYPE_TINY; q += 2; break;
412 case 'u': t[i] = APR_DBD_TYPE_UTINY; q += 2; break;
413 }
414 break;
415 case 'd': t[i] = APR_DBD_TYPE_SHORT; q++; break;
416 case 'u': t[i] = APR_DBD_TYPE_USHORT; q++; break;
417 }
418 break;
419 case 'l':
420 switch (q[2]) {
421 case 'l':
422 switch (q[3]){
423 case 'd': t[i] = APR_DBD_TYPE_LONGLONG; q += 2; break;
424 case 'u': t[i] = APR_DBD_TYPE_ULONGLONG; q += 2; break;
425 }
426 break;
427 case 'd': t[i] = APR_DBD_TYPE_LONG; q++; break;
428 case 'u': t[i] = APR_DBD_TYPE_ULONG; q++; break;
429 case 'f': t[i] = APR_DBD_TYPE_DOUBLE; q++; break;
430 }
431 break;
432 case 'p':
433 if (q[2] == 'D') {
434 switch (q[3]) {
435 case 't': t[i] = APR_DBD_TYPE_TEXT; q += 2; break;
436 case 'i': t[i] = APR_DBD_TYPE_TIME; q += 2; break;
437 case 'd': t[i] = APR_DBD_TYPE_DATE; q += 2; break;
438 case 'a': t[i] = APR_DBD_TYPE_DATETIME; q += 2; break;
439 case 's': t[i] = APR_DBD_TYPE_TIMESTAMP; q += 2; break;
440 case 'z': t[i] = APR_DBD_TYPE_ZTIMESTAMP; q += 2; break;
441 case 'b': t[i] = APR_DBD_TYPE_BLOB; q += 2; break;
442 case 'c': t[i] = APR_DBD_TYPE_CLOB; q += 2; break;
443 case 'n': t[i] = APR_DBD_TYPE_NULL; q += 2; break;
444 }
445 }
446 break;
447 }
448 q++;
449
450 switch (t[i]) {
451 case APR_DBD_TYPE_NONE: /* by default, we expect strings */
453 break;
455 case APR_DBD_TYPE_CLOB: /* three (3) more values passed in */
456 nvals += 3;
457 break;
458 default:
459 break;
460 }
461
462 /* insert database specific parameter reference */
463 p += apr_snprintf(p, qlen - (p - pq), driver->pformat, ++i);
464 } else if (q[1] == '%') { /* reduce %% to % */
465 *p++ = *q++;
466 } else {
467 *p++ = *q;
468 }
469 } else {
470 *p++ = *q;
471 }
472 }
473 *p = '\0';
474
476}
477
480 apr_dbd_t *handle, int *nrows,
482 int nargs, const char **args)
483{
485}
486
491 int nargs, const char **args)
492{
494}
495
508
513 int random, ...)
514{
515 int ret;
519 va_end(args);
520 return ret;
521}
522
525 apr_dbd_t *handle, int *nrows,
527 const void **args)
528{
530}
531
536 const void **args)
537{
539}
540
543 apr_dbd_t *handle, int *nrows,
545{
546 int ret;
550 va_end(args);
551 return ret;
552}
553
558 int random, ...)
559{
560 int ret;
564 va_end(args);
565 return ret;
566}
567
569 apr_dbd_row_t *row, int col,
570 apr_dbd_type_e type, void *data)
571{
572 return driver->datum_get(row,col,type,data);
573}
APR Atomic Operations.
static apr_hash_t * drivers
Definition apr_dbd.c:36
static apr_uint32_t initialised
Definition apr_dbd.c:37
static apr_uint32_t in_init
Definition apr_dbd.c:37
static apr_status_t apr_dbd_term(void *ptr)
Definition apr_dbd.c:79
#define CLEANUP_CAST
Definition apr_dbd.c:39
#define DRIVER_LOAD(name, driver, pool)
Definition apr_dbd.c:69
APR-UTIL DBD library.
APR Dynamic Object Handling Routines.
APR Hash Tables.
APR general purpose library routines.
APR memory allocation.
APU_DECLARE(void)
Computes SipHash-2-4, producing a 64bit (APR_SIPHASH_DSIZE) hash from a message and a 128bit (APR_SIP...
Definition apr_sha1.c:206
APR Strings library.
APR Thread Mutex Routines.
APR-util Versioning Interface.
#define APU_STRINGIFY(n)
Definition apu_version.h:87
#define APU_MAJOR_VERSION
Definition apu_version.h:53
apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem)
Definition atomic.c:51
int apr_atomic_dec32(volatile apr_uint32_t *mem)
Definition atomic.c:56
void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
Definition atomic.c:73
apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem)
Definition atomic.c:68
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_EINIT
Definition apr_errno.h:474
APU_DECLARE_NONSTD(void)
Definition apr_buckets.c:43
apr_pool_t apr_dbd_t const char * query
Definition apr_dbd.h:396
const char const apr_dbd_driver_t ** driver
Definition apr_dbd.h:106
apr_dbd_type_e
Definition apr_dbd.h:55
apr_pool_t const char apr_dbd_t const char ** error
Definition apr_dbd.h:143
struct apr_dbd_prepared_t apr_dbd_prepared_t
Definition apr_dbd.h:87
apr_pool_t apr_dbd_t const char const char * label
Definition apr_dbd.h:397
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
struct apr_dbd_t apr_dbd_t
Definition apr_dbd.h:83
apr_dbd_t int const char * statement
Definition apr_dbd.h:272
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
struct apr_dbd_results_t apr_dbd_results_t
Definition apr_dbd.h:85
apr_pool_t const char apr_dbd_t ** handle
Definition apr_dbd.h:142
apr_dbd_t int errnum
Definition apr_dbd.h:353
apr_pool_t apr_dbd_results_t apr_dbd_row_t int rownum
Definition apr_dbd.h:321
apr_pool_t apr_dbd_t int apr_dbd_prepared_t int nargs
Definition apr_dbd.h:414
struct apr_dbd_transaction_t apr_dbd_transaction_t
Definition apr_dbd.h:84
apr_pool_t apr_dbd_results_t apr_dbd_row_t ** row
Definition apr_dbd.h:320
apr_pool_t const char * params
Definition apr_dbd.h:141
apr_dbd_t int * nrows
Definition apr_dbd.h:272
struct apr_dbd_row_t apr_dbd_row_t
Definition apr_dbd.h:86
apr_dbd_row_t int col
Definition apr_dbd.h:331
@ APR_DBD_TYPE_SHORT
Definition apr_dbd.h:59
@ APR_DBD_TYPE_FLOAT
Definition apr_dbd.h:67
@ APR_DBD_TYPE_TIME
Definition apr_dbd.h:71
@ APR_DBD_TYPE_ULONG
Definition apr_dbd.h:64
@ APR_DBD_TYPE_STRING
Definition apr_dbd.h:69
@ APR_DBD_TYPE_INT
Definition apr_dbd.h:61
@ APR_DBD_TYPE_NONE
Definition apr_dbd.h:56
@ APR_DBD_TYPE_UINT
Definition apr_dbd.h:62
@ APR_DBD_TYPE_TIMESTAMP
Definition apr_dbd.h:74
@ APR_DBD_TYPE_BLOB
Definition apr_dbd.h:76
@ APR_DBD_TYPE_NULL
Definition apr_dbd.h:78
@ APR_DBD_TYPE_DATETIME
Definition apr_dbd.h:73
@ APR_DBD_TYPE_DOUBLE
Definition apr_dbd.h:68
@ APR_DBD_TYPE_LONGLONG
Definition apr_dbd.h:65
@ APR_DBD_TYPE_UTINY
Definition apr_dbd.h:58
@ APR_DBD_TYPE_DATE
Definition apr_dbd.h:72
@ APR_DBD_TYPE_TINY
Definition apr_dbd.h:57
@ APR_DBD_TYPE_ULONGLONG
Definition apr_dbd.h:66
@ APR_DBD_TYPE_LONG
Definition apr_dbd.h:63
@ APR_DBD_TYPE_CLOB
Definition apr_dbd.h:77
@ APR_DBD_TYPE_TEXT
Definition apr_dbd.h:70
@ APR_DBD_TYPE_ZTIMESTAMP
Definition apr_dbd.h:75
@ APR_DBD_TYPE_USHORT
Definition apr_dbd.h:60
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define apr_isalpha(c)
Definition apr_lib.h:205
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void * data
int type
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
apr_interval_time_t t
apr_pool_t * parent
Definition apr_pools.h:197
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
void * random
Definition apr_random.h:99
const char const char *const * args
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
static const char *const trans[040]
Definition sed1.c:28
char * name
int(* pvbselect)(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_results_t **res, apr_dbd_prepared_t *statement, int random, va_list args)
int(* transaction_mode_get)(apr_dbd_transaction_t *trans)
apr_dbd_t *(* open)(apr_pool_t *pool, const char *params, const char **error)
int(* set_dbname)(apr_pool_t *pool, apr_dbd_t *handle, const char *name)
int(* pselect)(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_results_t **res, apr_dbd_prepared_t *statement, int random, const char **args)
int(* select)(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_results_t **res, const char *statement, int random)
int(* prepare)(apr_pool_t *pool, apr_dbd_t *handle, const char *query, const char *label, int nargs, int nvals, apr_dbd_type_e *types, apr_dbd_prepared_t **statement)
int(* num_tuples)(apr_dbd_results_t *res)
int(* num_cols)(apr_dbd_results_t *res)
apr_status_t(* close)(apr_dbd_t *handle)
apr_status_t(* check_conn)(apr_pool_t *pool, apr_dbd_t *handle)
int(* start_transaction)(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_transaction_t **trans)
int(* transaction_mode_set)(apr_dbd_transaction_t *trans, int mode)
int(* pquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows, apr_dbd_prepared_t *statement, const char **args)
int(* end_transaction)(apr_dbd_transaction_t *trans)
const char *(* error)(apr_dbd_t *handle, int errnum)
int(* pvbquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows, apr_dbd_prepared_t *statement, va_list args)
int(* pvquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows, apr_dbd_prepared_t *statement, va_list args)
apr_status_t(* datum_get)(const apr_dbd_row_t *row, int col, apr_dbd_type_e type, void *data)
int(* pbselect)(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_results_t **res, apr_dbd_prepared_t *statement, int random, const void **args)
const char *(* get_entry)(const apr_dbd_row_t *row, int col)
int(* query)(apr_dbd_t *handle, int *nrows, const char *statement)
const char *(* get_name)(const apr_dbd_results_t *res, int col)
int(* pvselect)(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_results_t **res, apr_dbd_prepared_t *statement, int random, va_list args)
int(* get_row)(apr_pool_t *pool, apr_dbd_results_t *res, apr_dbd_row_t **row, int rownum)
const char *(* escape)(apr_pool_t *pool, const char *string, apr_dbd_t *handle)
int(* pbquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows, apr_dbd_prepared_t *statement, const void **args)
void *(* native_handle)(apr_dbd_t *handle)