Set *nrows in dbd_pgsql_pquery
[apr-util.git] / dbd / apr_dbd_sqlite2.c
blobc741a236b873a722429a6bdde9734f178ed20e84
1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
2 * applicable.
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.
17 #include "apu.h"
19 #if APU_HAVE_SQLITE2
21 #include <ctype.h>
22 #include <stdlib.h>
24 #include <sqlite.h>
26 #include "apr_strings.h"
27 #include "apr_time.h"
29 #include "apr_dbd_internal.h"
31 struct apr_dbd_transaction_t {
32 int errnum;
33 apr_dbd_t *handle;
36 struct apr_dbd_t {
37 sqlite *conn;
38 char *errmsg;
39 apr_dbd_transaction_t *trans;
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;
51 struct apr_dbd_row_t {
52 int n;
53 char **data;
54 apr_dbd_results_t *res;
57 struct apr_dbd_prepared_t {
58 const char *name;
59 int prepared;
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);
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)
75 char **result;
76 int ret = 0;
77 int tuples = 0;
78 int fields = 0;
80 if (sql->trans && sql->trans->errnum) {
81 return sql->trans->errnum;
84 FREE_ERROR_MSG(sql);
86 ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
87 &sql->errmsg);
89 if (ret == SQLITE_OK) {
90 if (!*results) {
91 *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
94 (*results)->res = result;
95 if (seek) {
96 (*results)->ntuples = tuples;
98 else {
99 (*results)->ntuples = -1;
101 (*results)->sz = fields;
102 (*results)->random = seek;
104 if (tuples > 0)
105 apr_pool_cleanup_register(pool, result, (void *) free,
106 apr_pool_cleanup_null);
108 ret = 0;
110 else {
111 sql->trans->errnum = ret;
114 return ret;
117 static const char *dbd_sqlite_get_name(const apr_dbd_results_t *res, int n)
119 if ((n < 0) || (n >= res->sz)) {
120 return NULL;
123 return res->res[n];
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;
132 if (row == NULL) {
133 row = apr_palloc(pool, sizeof(apr_dbd_row_t));
134 *rowp = row;
135 row->res = res;
136 row->n = sequential ? 0 : rownum - 1;
138 else {
139 if (sequential) {
140 ++row->n;
142 else {
143 row->n = rownum - 1;
147 if (row->n >= res->ntuples) {
148 *rowp = NULL;
149 apr_pool_cleanup_kill(pool, res->res, (void *) free);
150 res->res = NULL;
151 return -1;
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%';
160 nrow = 2
161 ncolumn = 3
162 result[0] = "employee_name"
163 result[1] = "login"
164 result[2] = "host"
165 result[3] = "dummy"
166 result[4] = "No such user"
167 result[5] = 0
168 result[6] = "D. Richard Hipp"
169 result[7] = "drh"
170 result[8] = "zadok"
173 row->data = res->res + res->sz + (res->sz * row->n);
175 return 0;
178 static const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
180 if ((n < 0) || (n >= row->res->sz)) {
181 return NULL;
184 return row->data[n];
187 static const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
189 return sql->errmsg;
192 static int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
194 char **result;
195 int ret;
196 int tuples = 0;
197 int fields = 0;
199 if (sql->trans && sql->trans->errnum) {
200 return sql->trans->errnum;
203 FREE_ERROR_MSG(sql);
205 ret =
206 sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
207 &sql->errmsg);
208 if (ret == SQLITE_OK) {
209 *nrows = sqlite_changes(sql->conn);
211 if (tuples > 0)
212 free(result);
214 ret = 0;
217 if (sql->trans) {
218 sql->trans->errnum = ret;
221 return ret;
224 static const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
225 apr_dbd_t * sql)
227 char *ret = sqlite_mprintf("%q", arg);
228 apr_pool_cleanup_register(pool, ret, (void *) sqlite_freemem,
229 apr_pool_cleanup_null);
230 return ret;
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)
237 return APR_ENOTIMPL;
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)
244 return APR_ENOTIMPL;
247 static int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
248 int *nrows, apr_dbd_prepared_t * statement,
249 va_list args)
251 return APR_ENOTIMPL;
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)
259 return APR_ENOTIMPL;
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,
265 va_list args)
267 return APR_ENOTIMPL;
270 static int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
271 apr_dbd_transaction_t ** trans)
273 int ret, rows;
275 ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION");
276 if (ret == 0) {
277 if (!*trans) {
278 *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
280 (*trans)->handle = handle;
281 handle->trans = *trans;
283 else {
284 ret = -1;
286 return ret;
289 static int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
291 int rows;
292 int ret = -1; /* no transaction is an error cond */
294 if (trans) {
295 if (trans->errnum) {
296 trans->errnum = 0;
297 ret =
298 dbd_sqlite_query(trans->handle, &rows,
299 "ROLLBACK TRANSACTION");
301 else {
302 ret =
303 dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
305 trans->handle->trans = NULL;
308 return ret;
311 static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_)
313 apr_dbd_t *sql;
314 sqlite *conn = NULL;
315 char *filename, *perm;
316 int iperms = 600;
317 char* params = apr_pstrdup(pool, params_);
318 /* params = "[filename]:[permissions]"
319 * example: "shopping.db:600"
322 perm = strstr(params, ":");
323 if (perm) {
324 *(perm++) = '\x00'; /* split the filename and permissions */
326 if (strlen(perm) > 0)
327 iperms = atoi(perm);
330 conn = sqlite_open(params, iperms, NULL);
332 sql = apr_pcalloc(pool, sizeof(*sql));
333 sql->conn = conn;
335 return sql;
338 static apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
340 if (handle->conn) {
341 sqlite_close(handle->conn);
342 handle->conn = NULL;
344 return APR_SUCCESS;
347 static apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
348 apr_dbd_t * handle)
350 if (handle->conn == NULL)
351 return -1;
352 return APR_SUCCESS;
355 static int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
356 const char *name)
358 return APR_ENOTIMPL;
361 static void *dbd_sqlite_native(apr_dbd_t * handle)
363 return handle->conn;
366 static int dbd_sqlite_num_cols(apr_dbd_results_t * res)
368 return res->sz;
371 static int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
373 return res->ntuples;
376 APU_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = {
377 "sqlite2",
378 NULL,
379 dbd_sqlite_native,
380 dbd_sqlite_open,
381 dbd_sqlite_check_conn,
382 dbd_sqlite_close,
383 dbd_sqlite_select_db,
384 dbd_sqlite_start_transaction,
385 dbd_sqlite_end_transaction,
386 dbd_sqlite_query,
387 dbd_sqlite_select,
388 dbd_sqlite_num_cols,
389 dbd_sqlite_num_tuples,
390 dbd_sqlite_get_row,
391 dbd_sqlite_get_entry,
392 dbd_sqlite_error,
393 dbd_sqlite_escape,
394 dbd_sqlite_prepare,
395 dbd_sqlite_pvquery,
396 dbd_sqlite_pvselect,
397 dbd_sqlite_pquery,
398 dbd_sqlite_pselect,
399 dbd_sqlite_get_name
401 #endif