1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
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
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"
29 #include "apr_dbd_internal.h"
31 struct apr_dbd_transaction_t
{
39 apr_dbd_transaction_t
*trans
;
42 struct apr_dbd_results_t
{
51 struct apr_dbd_row_t
{
54 apr_dbd_results_t
*res
;
57 struct apr_dbd_prepared_t
{
62 #define FREE_ERROR_MSG(dbd) \
64 if(dbd && dbd->errmsg) { \
71 static int dbd_sqlite_select(apr_pool_t
* pool
, apr_dbd_t
* sql
,
72 apr_dbd_results_t
** results
, const char *query
,
80 if (sql
->trans
&& sql
->trans
->errnum
) {
81 return sql
->trans
->errnum
;
86 ret
= sqlite_get_table(sql
->conn
, query
, &result
, &tuples
, &fields
,
89 if (ret
== SQLITE_OK
) {
91 *results
= apr_pcalloc(pool
, sizeof(apr_dbd_results_t
));
94 (*results
)->res
= result
;
96 (*results
)->ntuples
= tuples
;
99 (*results
)->ntuples
= -1;
101 (*results
)->sz
= fields
;
102 (*results
)->random
= seek
;
105 apr_pool_cleanup_register(pool
, result
, (void *) free
,
106 apr_pool_cleanup_null
);
111 sql
->trans
->errnum
= ret
;
117 static const char *dbd_sqlite_get_name(const apr_dbd_results_t
*res
, int n
)
119 if ((n
< 0) || (n
>= res
->sz
)) {
126 static int dbd_sqlite_get_row(apr_pool_t
* pool
, apr_dbd_results_t
* res
,
127 apr_dbd_row_t
** rowp
, int rownum
)
129 apr_dbd_row_t
*row
= *rowp
;
130 int sequential
= ((rownum
>= 0) && res
->random
) ? 0 : 1;
133 row
= apr_palloc(pool
, sizeof(apr_dbd_row_t
));
136 row
->n
= sequential
? 0 : rownum
- 1;
147 if (row
->n
>= res
->ntuples
) {
149 apr_pool_cleanup_kill(pool
, res
->res
, (void *) free
);
154 /* Pointer magic explanation:
155 * The sqlite result is an array such that the first res->sz elements are
156 * the column names and each tuple follows afterwards
157 * ex: (from the sqlite2 documentation)
158 SELECT employee_name, login, host FROM users WHERE login LIKE * 'd%';
162 result[0] = "employee_name"
166 result[4] = "No such user"
168 result[6] = "D. Richard Hipp"
173 row
->data
= res
->res
+ res
->sz
+ (res
->sz
* row
->n
);
178 static const char *dbd_sqlite_get_entry(const apr_dbd_row_t
* row
, int n
)
180 if ((n
< 0) || (n
>= row
->res
->sz
)) {
187 static const char *dbd_sqlite_error(apr_dbd_t
* sql
, int n
)
192 static int dbd_sqlite_query(apr_dbd_t
* sql
, int *nrows
, const char *query
)
199 if (sql
->trans
&& sql
->trans
->errnum
) {
200 return sql
->trans
->errnum
;
206 sqlite_get_table(sql
->conn
, query
, &result
, &tuples
, &fields
,
208 if (ret
== SQLITE_OK
) {
209 *nrows
= sqlite_changes(sql
->conn
);
218 sql
->trans
->errnum
= ret
;
224 static const char *dbd_sqlite_escape(apr_pool_t
* pool
, const char *arg
,
227 char *ret
= sqlite_mprintf("%q", arg
);
228 apr_pool_cleanup_register(pool
, ret
, (void *) sqlite_freemem
,
229 apr_pool_cleanup_null
);
233 static int dbd_sqlite_prepare(apr_pool_t
* pool
, apr_dbd_t
* sql
,
234 const char *query
, const char *label
,
235 apr_dbd_prepared_t
** statement
)
240 static int dbd_sqlite_pquery(apr_pool_t
* pool
, apr_dbd_t
* sql
,
241 int *nrows
, apr_dbd_prepared_t
* statement
,
242 int nargs
, const char **values
)
247 static int dbd_sqlite_pvquery(apr_pool_t
* pool
, apr_dbd_t
* sql
,
248 int *nrows
, apr_dbd_prepared_t
* statement
,
254 static int dbd_sqlite_pselect(apr_pool_t
* pool
, apr_dbd_t
* sql
,
255 apr_dbd_results_t
** results
,
256 apr_dbd_prepared_t
* statement
,
257 int seek
, int nargs
, const char **values
)
262 static int dbd_sqlite_pvselect(apr_pool_t
* pool
, apr_dbd_t
* sql
,
263 apr_dbd_results_t
** results
,
264 apr_dbd_prepared_t
* statement
, int seek
,
270 static int dbd_sqlite_start_transaction(apr_pool_t
* pool
, apr_dbd_t
* handle
,
271 apr_dbd_transaction_t
** trans
)
275 ret
= dbd_sqlite_query(handle
, &rows
, "BEGIN TRANSACTION");
278 *trans
= apr_pcalloc(pool
, sizeof(apr_dbd_transaction_t
));
280 (*trans
)->handle
= handle
;
281 handle
->trans
= *trans
;
289 static int dbd_sqlite_end_transaction(apr_dbd_transaction_t
* trans
)
292 int ret
= -1; /* no transaction is an error cond */
298 dbd_sqlite_query(trans
->handle
, &rows
,
299 "ROLLBACK TRANSACTION");
303 dbd_sqlite_query(trans
->handle
, &rows
, "COMMIT TRANSACTION");
305 trans
->handle
->trans
= NULL
;
311 static apr_dbd_t
*dbd_sqlite_open(apr_pool_t
* pool
, const char *params_
)
315 char *filename
, *perm
;
317 char* params
= apr_pstrdup(pool
, params_
);
318 /* params = "[filename]:[permissions]"
319 * example: "shopping.db:600"
322 perm
= strstr(params
, ":");
324 *(perm
++) = '\x00'; /* split the filename and permissions */
326 if (strlen(perm
) > 0)
330 conn
= sqlite_open(params
, iperms
, NULL
);
332 sql
= apr_pcalloc(pool
, sizeof(*sql
));
338 static apr_status_t
dbd_sqlite_close(apr_dbd_t
* handle
)
341 sqlite_close(handle
->conn
);
347 static apr_status_t
dbd_sqlite_check_conn(apr_pool_t
* pool
,
350 if (handle
->conn
== NULL
)
355 static int dbd_sqlite_select_db(apr_pool_t
* pool
, apr_dbd_t
* handle
,
361 static void *dbd_sqlite_native(apr_dbd_t
* handle
)
366 static int dbd_sqlite_num_cols(apr_dbd_results_t
* res
)
371 static int dbd_sqlite_num_tuples(apr_dbd_results_t
* res
)
376 APU_DECLARE_DATA
const apr_dbd_driver_t apr_dbd_sqlite2_driver
= {
381 dbd_sqlite_check_conn
,
383 dbd_sqlite_select_db
,
384 dbd_sqlite_start_transaction
,
385 dbd_sqlite_end_transaction
,
389 dbd_sqlite_num_tuples
,
391 dbd_sqlite_get_entry
,