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 + -
显示快捷键?