123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
- * applicable.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "apu.h"
- #if APU_HAVE_SQLITE2
- #include <ctype.h>
- #include <stdlib.h>
- #include <sqlite.h>
- #include "apr_strings.h"
- #include "apr_time.h"
- #include "apr_dbd_internal.h"
- struct apr_dbd_transaction_t {
- int errnum;
- apr_dbd_t *handle;
- };
- struct apr_dbd_t {
- sqlite *conn;
- char *errmsg;
- apr_dbd_transaction_t *trans;
- };
- struct apr_dbd_results_t {
- int random;
- sqlite *handle;
- char **res;
- size_t ntuples;
- size_t sz;
- size_t index;
- };
- struct apr_dbd_row_t {
- int n;
- char **data;
- apr_dbd_results_t *res;
- };
- struct apr_dbd_prepared_t {
- const char *name;
- int prepared;
- };
- #define FREE_ERROR_MSG(dbd) \
- do { \
- if(dbd && dbd->errmsg) { \
- free(dbd->errmsg); \
- dbd->errmsg = NULL; \
- } \
- } while(0);
- static apr_status_t free_table(void *data)
- {
- sqlite_free_table(data);
- return APR_SUCCESS;
- }
- static int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql,
- apr_dbd_results_t ** results, const char *query,
- int seek)
- {
- char **result;
- int ret = 0;
- int tuples = 0;
- int fields = 0;
- if (sql->trans && sql->trans->errnum) {
- return sql->trans->errnum;
- }
- FREE_ERROR_MSG(sql);
- ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
- &sql->errmsg);
- if (ret == SQLITE_OK) {
- if (!*results) {
- *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
- }
- (*results)->res = result;
- (*results)->ntuples = tuples;
- (*results)->sz = fields;
- (*results)->random = seek;
- if (tuples > 0)
- apr_pool_cleanup_register(pool, result, free_table,
- apr_pool_cleanup_null);
- ret = 0;
- }
- else {
- sql->trans->errnum = ret;
- }
- return ret;
- }
- static int dbd_sqlite_get_row(apr_pool_t * pool, apr_dbd_results_t * res,
- apr_dbd_row_t ** rowp, int rownum)
- {
- apr_dbd_row_t *row = *rowp;
- int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
- if (row == NULL) {
- row = apr_palloc(pool, sizeof(apr_dbd_row_t));
- *rowp = row;
- row->res = res;
- row->n = sequential ? 0 : rownum - 1;
- }
- else {
- if (sequential) {
- ++row->n;
- }
- else {
- row->n = rownum - 1;
- }
- }
- if (row->n >= res->ntuples) {
- *rowp = NULL;
- apr_pool_cleanup_run(pool, res->res, free_table);
- res->res = NULL;
- return -1;
- }
- /* Pointer magic explanation:
- * The sqlite result is an array such that the first res->sz elements are
- * the column names and each tuple follows afterwards
- * ex: (from the sqlite2 documentation)
- SELECT employee_name, login, host FROM users WHERE login LIKE * 'd%';
- nrow = 2
- ncolumn = 3
- result[0] = "employee_name"
- result[1] = "login"
- result[2] = "host"
- result[3] = "dummy"
- result[4] = "No such user"
- result[5] = 0
- result[6] = "D. Richard Hipp"
- result[7] = "drh"
- result[8] = "zadok"
- */
- row->data = res->res + res->sz + (res->sz * row->n);
- return 0;
- }
- static const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
- {
- if ((n < 0) || (n >= row->res->sz)) {
- return NULL;
- }
- return row->data[n];
- }
- static const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
- {
- return sql->errmsg;
- }
- static int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
- {
- char **result;
- int ret;
- int tuples = 0;
- int fields = 0;
- if (sql->trans && sql->trans->errnum) {
- return sql->trans->errnum;
- }
- FREE_ERROR_MSG(sql);
- ret =
- sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
- &sql->errmsg);
- if (ret == SQLITE_OK) {
- *nrows = sqlite_changes(sql->conn);
- if (tuples > 0)
- free(result);
- ret = 0;
- }
- if (sql->trans) {
- sql->trans->errnum = ret;
- }
- return ret;
- }
- static apr_status_t free_mem(void *data)
- {
- sqlite_freemem(data);
- return APR_SUCCESS;
- }
- static const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
- apr_dbd_t * sql)
- {
- char *ret = sqlite_mprintf("%q", arg);
- apr_pool_cleanup_register(pool, ret, free_mem, apr_pool_cleanup_null);
- return ret;
- }
- static int dbd_sqlite_prepare(apr_pool_t * pool, apr_dbd_t * sql,
- const char *query, const char *label,
- apr_dbd_prepared_t ** statement)
- {
- return APR_ENOTIMPL;
- }
- static int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql,
- int *nrows, apr_dbd_prepared_t * statement,
- int nargs, const char **values)
- {
- return APR_ENOTIMPL;
- }
- static int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
- int *nrows, apr_dbd_prepared_t * statement,
- va_list args)
- {
- return APR_ENOTIMPL;
- }
- static int dbd_sqlite_pselect(apr_pool_t * pool, apr_dbd_t * sql,
- apr_dbd_results_t ** results,
- apr_dbd_prepared_t * statement,
- int seek, int nargs, const char **values)
- {
- return APR_ENOTIMPL;
- }
- static int dbd_sqlite_pvselect(apr_pool_t * pool, apr_dbd_t * sql,
- apr_dbd_results_t ** results,
- apr_dbd_prepared_t * statement, int seek,
- va_list args)
- {
- return APR_ENOTIMPL;
- }
- static int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
- apr_dbd_transaction_t ** trans)
- {
- int ret, rows;
- ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION");
- if (ret == 0) {
- if (!*trans) {
- *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
- }
- (*trans)->handle = handle;
- handle->trans = *trans;
- }
- else {
- ret = -1;
- }
- return ret;
- }
- static int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
- {
- int rows;
- int ret = -1; /* no transaction is an error cond */
- if (trans) {
- if (trans->errnum) {
- trans->errnum = 0;
- ret =
- dbd_sqlite_query(trans->handle, &rows,
- "ROLLBACK TRANSACTION");
- }
- else {
- ret =
- dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
- }
- trans->handle->trans = NULL;
- }
- return ret;
- }
- static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_)
- {
- apr_dbd_t *sql;
- sqlite *conn = NULL;
- char *perm;
- int iperms = 600;
- char* params = apr_pstrdup(pool, params_);
- /* params = "[filename]:[permissions]"
- * example: "shopping.db:600"
- */
- perm = strstr(params, ":");
- if (perm) {
- *(perm++) = '\x00'; /* split the filename and permissions */
- if (strlen(perm) > 0)
- iperms = atoi(perm);
- }
- conn = sqlite_open(params, iperms, NULL);
- sql = apr_pcalloc(pool, sizeof(*sql));
- sql->conn = conn;
- return sql;
- }
- static apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
- {
- if (handle->conn) {
- sqlite_close(handle->conn);
- handle->conn = NULL;
- }
- return APR_SUCCESS;
- }
- static apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
- apr_dbd_t * handle)
- {
- if (handle->conn == NULL)
- return -1;
- return APR_SUCCESS;
- }
- static int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
- const char *name)
- {
- return APR_ENOTIMPL;
- }
- static void *dbd_sqlite_native(apr_dbd_t * handle)
- {
- return handle->conn;
- }
- static int dbd_sqlite_num_cols(apr_dbd_results_t * res)
- {
- return res->sz;
- }
- static int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
- {
- return res->ntuples;
- }
- APU_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = {
- "sqlite2",
- NULL,
- dbd_sqlite_native,
- dbd_sqlite_open,
- dbd_sqlite_check_conn,
- dbd_sqlite_close,
- dbd_sqlite_select_db,
- dbd_sqlite_start_transaction,
- dbd_sqlite_end_transaction,
- dbd_sqlite_query,
- dbd_sqlite_select,
- dbd_sqlite_num_cols,
- dbd_sqlite_num_tuples,
- dbd_sqlite_get_row,
- dbd_sqlite_get_entry,
- dbd_sqlite_error,
- dbd_sqlite_escape,
- dbd_sqlite_prepare,
- dbd_sqlite_pvquery,
- dbd_sqlite_pvselect,
- dbd_sqlite_pquery,
- dbd_sqlite_pselect,
- };
- #endif
|