apr_dbd_sqlite2.c

来自「linux网络服务器工具」· C语言 代码 · 共 567 行

C
567
字号
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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_buckets.h"#include "apr_dbd_internal.h"struct apr_dbd_transaction_t {    int mode;    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;    apr_pool_t *pool;};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;        (*results)->pool = pool;        if (tuples > 0)            apr_pool_cleanup_register(pool, result, free_table,                                      apr_pool_cleanup_null);        ret = 0;    }    else {        if (TXN_NOTICE_ERRORS(sql->trans)) {            sql->trans->errnum = ret;        }    }    return ret;}static const char *dbd_sqlite_get_name(const apr_dbd_results_t *res, int n){    if ((n < 0) || (n >= res->sz)) {        return NULL;    }    return res->res[n];}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 apr_status_t dbd_sqlite_datum_get(const apr_dbd_row_t *row, int n,                                         apr_dbd_type_e type, void *data){    if ((n < 0) || (n >= row->res->sz)) {      return APR_EGENERAL;    }    if (row->data[n] == NULL) {        return APR_ENOENT;    }    switch (type) {    case APR_DBD_TYPE_TINY:        *(char*)data = atoi(row->data[n]);        break;    case APR_DBD_TYPE_UTINY:        *(unsigned char*)data = atoi(row->data[n]);        break;    case APR_DBD_TYPE_SHORT:        *(short*)data = atoi(row->data[n]);        break;    case APR_DBD_TYPE_USHORT:        *(unsigned short*)data = atoi(row->data[n]);        break;    case APR_DBD_TYPE_INT:        *(int*)data = atoi(row->data[n]);        break;    case APR_DBD_TYPE_UINT:        *(unsigned int*)data = atoi(row->data[n]);        break;    case APR_DBD_TYPE_LONG:        *(long*)data = atol(row->data[n]);        break;    case APR_DBD_TYPE_ULONG:        *(unsigned long*)data = atol(row->data[n]);        break;    case APR_DBD_TYPE_LONGLONG:        *(apr_int64_t*)data = apr_atoi64(row->data[n]);        break;    case APR_DBD_TYPE_ULONGLONG:        *(apr_uint64_t*)data = apr_atoi64(row->data[n]);        break;    case APR_DBD_TYPE_FLOAT:        *(float*)data = atof(row->data[n]);        break;    case APR_DBD_TYPE_DOUBLE:        *(double*)data = atof(row->data[n]);        break;    case APR_DBD_TYPE_STRING:    case APR_DBD_TYPE_TEXT:    case APR_DBD_TYPE_TIME:    case APR_DBD_TYPE_DATE:    case APR_DBD_TYPE_DATETIME:    case APR_DBD_TYPE_TIMESTAMP:    case APR_DBD_TYPE_ZTIMESTAMP:        *(char**)data = row->data[n];        break;    case APR_DBD_TYPE_BLOB:    case APR_DBD_TYPE_CLOB:        {        apr_bucket *e;        apr_bucket_brigade *b = (apr_bucket_brigade*)data;        e = apr_bucket_pool_create(row->data[n],strlen(row->data[n]),                                   row->res->pool, b->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(b, e);        }        break;    case APR_DBD_TYPE_NULL:        *(void**)data = NULL;        break;    default:        return APR_EGENERAL;    }    return APR_SUCCESS;}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 (TXN_NOTICE_ERRORS(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,                              int nargs, int nvals, apr_dbd_type_e *types,                              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,                             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, 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_pbquery(apr_pool_t * pool, apr_dbd_t * sql,                              int *nrows, apr_dbd_prepared_t * statement,                              const void **values){    return APR_ENOTIMPL;}static int dbd_sqlite_pvbquery(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_pbselect(apr_pool_t * pool, apr_dbd_t * sql,                               apr_dbd_results_t ** results,                               apr_dbd_prepared_t * statement,                               int seek, const void **values){    return APR_ENOTIMPL;}static int dbd_sqlite_pvbselect(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) {        /* rollback on error or explicit rollback request */        if (trans->errnum || TXN_DO_ROLLBACK(trans)) {            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 int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans){    if (!trans)        return APR_DBD_TRANSACTION_COMMIT;    return trans->mode;}static int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans,                                           int mode){    if (!trans)        return APR_DBD_TRANSACTION_COMMIT;    return trans->mode = (mode & TXN_MODE_BITS);}static apr_status_t error_free(void *data){    free(data);    return APR_SUCCESS;}static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_,                                  const char **error){    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);    }    if (error) {        *error = NULL;        conn = sqlite_open(params, iperms, (char **)error);        if (*error) {            apr_pool_cleanup_register(pool, *error, error_free,                                      apr_pool_cleanup_null);        }    }    else {        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_MODULE_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,    dbd_sqlite_get_name,    dbd_sqlite_transaction_mode_get,    dbd_sqlite_transaction_mode_set,    NULL,    dbd_sqlite_pvbquery,    dbd_sqlite_pvbselect,    dbd_sqlite_pbquery,    dbd_sqlite_pbselect,    dbd_sqlite_datum_get};#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?