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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include "apr_strings.h"
28 #include "apr_buckets.h"
30 #include "apr_dbd_internal.h"
32 struct apr_dbd_transaction_t
{
41 apr_dbd_transaction_t
*trans
;
44 struct apr_dbd_results_t
{
54 struct apr_dbd_row_t
{
57 apr_dbd_results_t
*res
;
60 struct apr_dbd_prepared_t
{
65 #define FREE_ERROR_MSG(dbd) \
67 if(dbd && dbd->errmsg) { \
73 static apr_status_t
free_table(void *data
)
75 sqlite_free_table(data
);
79 static int dbd_sqlite_select(apr_pool_t
* pool
, apr_dbd_t
* sql
,
80 apr_dbd_results_t
** results
, const char *query
,
88 if (sql
->trans
&& sql
->trans
->errnum
) {
89 return sql
->trans
->errnum
;
94 ret
= sqlite_get_table(sql
->conn
, query
, &result
, &tuples
, &fields
,
97 if (ret
== SQLITE_OK
) {
99 *results
= apr_pcalloc(pool
, sizeof(apr_dbd_results_t
));
102 (*results
)->res
= result
;
103 (*results
)->ntuples
= tuples
;
104 (*results
)->sz
= fields
;
105 (*results
)->random
= seek
;
106 (*results
)->pool
= pool
;
109 apr_pool_cleanup_register(pool
, result
, free_table
,
110 apr_pool_cleanup_null
);
115 if (TXN_NOTICE_ERRORS(sql
->trans
)) {
116 sql
->trans
->errnum
= ret
;
123 static const char *dbd_sqlite_get_name(const apr_dbd_results_t
*res
, int n
)
125 if ((n
< 0) || (n
>= res
->sz
)) {
132 static int dbd_sqlite_get_row(apr_pool_t
* pool
, apr_dbd_results_t
* res
,
133 apr_dbd_row_t
** rowp
, int rownum
)
135 apr_dbd_row_t
*row
= *rowp
;
136 int sequential
= ((rownum
>= 0) && res
->random
) ? 0 : 1;
139 row
= apr_palloc(pool
, sizeof(apr_dbd_row_t
));
142 row
->n
= sequential
? 0 : rownum
- 1;
153 if (row
->n
>= res
->ntuples
) {
155 apr_pool_cleanup_run(pool
, res
->res
, free_table
);
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%';
168 result[0] = "employee_name"
172 result[4] = "No such user"
174 result[6] = "D. Richard Hipp"
179 row
->data
= res
->res
+ res
->sz
+ (res
->sz
* row
->n
);
184 static const char *dbd_sqlite_get_entry(const apr_dbd_row_t
* row
, int n
)
186 if ((n
< 0) || (n
>= row
->res
->sz
)) {
193 static apr_status_t
dbd_sqlite_datum_get(const apr_dbd_row_t
*row
, int n
,
194 apr_dbd_type_e type
, void *data
)
196 if ((n
< 0) || (n
>= row
->res
->sz
)) {
200 if (row
->data
[n
] == NULL
) {
205 case APR_DBD_TYPE_TINY
:
206 *(char*)data
= atoi(row
->data
[n
]);
208 case APR_DBD_TYPE_UTINY
:
209 *(unsigned char*)data
= atoi(row
->data
[n
]);
211 case APR_DBD_TYPE_SHORT
:
212 *(short*)data
= atoi(row
->data
[n
]);
214 case APR_DBD_TYPE_USHORT
:
215 *(unsigned short*)data
= atoi(row
->data
[n
]);
217 case APR_DBD_TYPE_INT
:
218 *(int*)data
= atoi(row
->data
[n
]);
220 case APR_DBD_TYPE_UINT
:
221 *(unsigned int*)data
= atoi(row
->data
[n
]);
223 case APR_DBD_TYPE_LONG
:
224 *(long*)data
= atol(row
->data
[n
]);
226 case APR_DBD_TYPE_ULONG
:
227 *(unsigned long*)data
= atol(row
->data
[n
]);
229 case APR_DBD_TYPE_LONGLONG
:
230 *(apr_int64_t
*)data
= apr_atoi64(row
->data
[n
]);
232 case APR_DBD_TYPE_ULONGLONG
:
233 *(apr_uint64_t
*)data
= apr_atoi64(row
->data
[n
]);
235 case APR_DBD_TYPE_FLOAT
:
236 *(float*)data
= atof(row
->data
[n
]);
238 case APR_DBD_TYPE_DOUBLE
:
239 *(double*)data
= atof(row
->data
[n
]);
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
];
250 case APR_DBD_TYPE_BLOB
:
251 case APR_DBD_TYPE_CLOB
:
254 apr_bucket_brigade
*b
= (apr_bucket_brigade
*)data
;
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
);
261 case APR_DBD_TYPE_NULL
:
262 *(void**)data
= NULL
;
271 static const char *dbd_sqlite_error(apr_dbd_t
* sql
, int n
)
276 static int dbd_sqlite_query(apr_dbd_t
* sql
, int *nrows
, const char *query
)
283 if (sql
->trans
&& sql
->trans
->errnum
) {
284 return sql
->trans
->errnum
;
290 sqlite_get_table(sql
->conn
, query
, &result
, &tuples
, &fields
,
292 if (ret
== SQLITE_OK
) {
293 *nrows
= sqlite_changes(sql
->conn
);
301 if (TXN_NOTICE_ERRORS(sql
->trans
)) {
302 sql
->trans
->errnum
= ret
;
308 static apr_status_t
free_mem(void *data
)
310 sqlite_freemem(data
);
314 static const char *dbd_sqlite_escape(apr_pool_t
* pool
, const char *arg
,
317 char *ret
= sqlite_mprintf("%q", arg
);
318 apr_pool_cleanup_register(pool
, ret
, free_mem
, apr_pool_cleanup_null
);
322 static 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
)
330 static int dbd_sqlite_pquery(apr_pool_t
* pool
, apr_dbd_t
* sql
,
331 int *nrows
, apr_dbd_prepared_t
* statement
,
337 static int dbd_sqlite_pvquery(apr_pool_t
* pool
, apr_dbd_t
* sql
,
338 int *nrows
, apr_dbd_prepared_t
* statement
,
344 static 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
)
352 static 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
,
360 static int dbd_sqlite_pbquery(apr_pool_t
* pool
, apr_dbd_t
* sql
,
361 int *nrows
, apr_dbd_prepared_t
* statement
,
367 static int dbd_sqlite_pvbquery(apr_pool_t
* pool
, apr_dbd_t
* sql
,
368 int *nrows
, apr_dbd_prepared_t
* statement
,
374 static 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
)
382 static 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
,
390 static int dbd_sqlite_start_transaction(apr_pool_t
* pool
, apr_dbd_t
* handle
,
391 apr_dbd_transaction_t
** trans
)
395 ret
= dbd_sqlite_query(handle
, &rows
, "BEGIN TRANSACTION");
398 *trans
= apr_pcalloc(pool
, sizeof(apr_dbd_transaction_t
));
400 (*trans
)->handle
= handle
;
401 handle
->trans
= *trans
;
409 static int dbd_sqlite_end_transaction(apr_dbd_transaction_t
* trans
)
412 int ret
= -1; /* no transaction is an error cond */
415 /* rollback on error or explicit rollback request */
416 if (trans
->errnum
|| TXN_DO_ROLLBACK(trans
)) {
419 dbd_sqlite_query(trans
->handle
, &rows
,
420 "ROLLBACK TRANSACTION");
424 dbd_sqlite_query(trans
->handle
, &rows
, "COMMIT TRANSACTION");
426 trans
->handle
->trans
= NULL
;
432 static int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t
*trans
)
435 return APR_DBD_TRANSACTION_COMMIT
;
440 static int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t
*trans
,
444 return APR_DBD_TRANSACTION_COMMIT
;
446 return trans
->mode
= (mode
& TXN_MODE_BITS
);
449 static apr_status_t
error_free(void *data
)
455 static apr_dbd_t
*dbd_sqlite_open(apr_pool_t
* pool
, const char *params_
,
462 char* params
= apr_pstrdup(pool
, params_
);
463 /* params = "[filename]:[permissions]"
464 * example: "shopping.db:600"
467 perm
= strstr(params
, ":");
469 *(perm
++) = '\x00'; /* split the filename and permissions */
471 if (strlen(perm
) > 0)
478 conn
= sqlite_open(params
, iperms
, (char **)error
);
481 apr_pool_cleanup_register(pool
, *error
, error_free
,
482 apr_pool_cleanup_null
);
486 conn
= sqlite_open(params
, iperms
, NULL
);
489 sql
= apr_pcalloc(pool
, sizeof(*sql
));
495 static apr_status_t
dbd_sqlite_close(apr_dbd_t
* handle
)
498 sqlite_close(handle
->conn
);
504 static apr_status_t
dbd_sqlite_check_conn(apr_pool_t
* pool
,
507 if (handle
->conn
== NULL
)
512 static int dbd_sqlite_select_db(apr_pool_t
* pool
, apr_dbd_t
* handle
,
518 static void *dbd_sqlite_native(apr_dbd_t
* handle
)
523 static int dbd_sqlite_num_cols(apr_dbd_results_t
* res
)
528 static int dbd_sqlite_num_tuples(apr_dbd_results_t
* res
)
533 APU_MODULE_DECLARE_DATA
const apr_dbd_driver_t apr_dbd_sqlite2_driver
= {
538 dbd_sqlite_check_conn
,
540 dbd_sqlite_select_db
,
541 dbd_sqlite_start_transaction
,
542 dbd_sqlite_end_transaction
,
546 dbd_sqlite_num_tuples
,
548 dbd_sqlite_get_entry
,
557 dbd_sqlite_transaction_mode_get
,
558 dbd_sqlite_transaction_mode_set
,
561 dbd_sqlite_pvbselect
,