1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter#include "apu.h" 18251876Speter 19251876Speter#if APU_HAVE_SQLITE2 20251876Speter 21251876Speter#include <ctype.h> 22251876Speter#include <stdlib.h> 23251876Speter 24251876Speter#include <sqlite.h> 25251876Speter 26251876Speter#include "apr_strings.h" 27251876Speter#include "apr_time.h" 28251876Speter#include "apr_buckets.h" 29251876Speter 30251876Speter#include "apr_dbd_internal.h" 31251876Speter 32251876Speterstruct apr_dbd_transaction_t { 33251876Speter int mode; 34251876Speter int errnum; 35251876Speter apr_dbd_t *handle; 36251876Speter}; 37251876Speter 38251876Speterstruct apr_dbd_t { 39251876Speter sqlite *conn; 40251876Speter char *errmsg; 41251876Speter apr_dbd_transaction_t *trans; 42251876Speter}; 43251876Speter 44251876Speterstruct apr_dbd_results_t { 45251876Speter int random; 46251876Speter sqlite *handle; 47251876Speter char **res; 48251876Speter size_t ntuples; 49251876Speter size_t sz; 50251876Speter size_t index; 51251876Speter apr_pool_t *pool; 52251876Speter}; 53251876Speter 54251876Speterstruct apr_dbd_row_t { 55251876Speter int n; 56251876Speter char **data; 57251876Speter apr_dbd_results_t *res; 58251876Speter}; 59251876Speter 60251876Speterstruct apr_dbd_prepared_t { 61251876Speter const char *name; 62251876Speter int prepared; 63251876Speter}; 64251876Speter 65251876Speter#define FREE_ERROR_MSG(dbd) \ 66251876Speter do { \ 67251876Speter if(dbd && dbd->errmsg) { \ 68251876Speter free(dbd->errmsg); \ 69251876Speter dbd->errmsg = NULL; \ 70251876Speter } \ 71251876Speter } while(0); 72251876Speter 73251876Speterstatic apr_status_t free_table(void *data) 74251876Speter{ 75251876Speter sqlite_free_table(data); 76251876Speter return APR_SUCCESS; 77251876Speter} 78251876Speter 79251876Speterstatic int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql, 80251876Speter apr_dbd_results_t ** results, const char *query, 81251876Speter int seek) 82251876Speter{ 83251876Speter char **result; 84251876Speter int ret = 0; 85251876Speter int tuples = 0; 86251876Speter int fields = 0; 87251876Speter 88251876Speter if (sql->trans && sql->trans->errnum) { 89251876Speter return sql->trans->errnum; 90251876Speter } 91251876Speter 92251876Speter FREE_ERROR_MSG(sql); 93251876Speter 94251876Speter ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields, 95251876Speter &sql->errmsg); 96251876Speter 97251876Speter if (ret == SQLITE_OK) { 98251876Speter if (!*results) { 99251876Speter *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t)); 100251876Speter } 101251876Speter 102251876Speter (*results)->res = result; 103251876Speter (*results)->ntuples = tuples; 104251876Speter (*results)->sz = fields; 105251876Speter (*results)->random = seek; 106251876Speter (*results)->pool = pool; 107251876Speter 108251876Speter if (tuples > 0) 109251876Speter apr_pool_cleanup_register(pool, result, free_table, 110251876Speter apr_pool_cleanup_null); 111251876Speter 112251876Speter ret = 0; 113251876Speter } 114251876Speter else { 115251876Speter if (TXN_NOTICE_ERRORS(sql->trans)) { 116251876Speter sql->trans->errnum = ret; 117251876Speter } 118251876Speter } 119251876Speter 120251876Speter return ret; 121251876Speter} 122251876Speter 123251876Speterstatic const char *dbd_sqlite_get_name(const apr_dbd_results_t *res, int n) 124251876Speter{ 125251876Speter if ((n < 0) || (n >= res->sz)) { 126251876Speter return NULL; 127251876Speter } 128251876Speter 129251876Speter return res->res[n]; 130251876Speter} 131251876Speter 132251876Speterstatic int dbd_sqlite_get_row(apr_pool_t * pool, apr_dbd_results_t * res, 133251876Speter apr_dbd_row_t ** rowp, int rownum) 134251876Speter{ 135251876Speter apr_dbd_row_t *row = *rowp; 136251876Speter int sequential = ((rownum >= 0) && res->random) ? 0 : 1; 137251876Speter 138251876Speter if (row == NULL) { 139251876Speter row = apr_palloc(pool, sizeof(apr_dbd_row_t)); 140251876Speter *rowp = row; 141251876Speter row->res = res; 142251876Speter row->n = sequential ? 0 : rownum - 1; 143251876Speter } 144251876Speter else { 145251876Speter if (sequential) { 146251876Speter ++row->n; 147251876Speter } 148251876Speter else { 149251876Speter row->n = rownum - 1; 150251876Speter } 151251876Speter } 152251876Speter 153251876Speter if (row->n >= res->ntuples) { 154251876Speter *rowp = NULL; 155253734Speter apr_pool_cleanup_run(res->pool, res->res, free_table); 156251876Speter res->res = NULL; 157251876Speter return -1; 158251876Speter } 159251876Speter 160251876Speter /* Pointer magic explanation: 161251876Speter * The sqlite result is an array such that the first res->sz elements are 162251876Speter * the column names and each tuple follows afterwards 163251876Speter * ex: (from the sqlite2 documentation) 164251876Speter SELECT employee_name, login, host FROM users WHERE login LIKE * 'd%'; 165251876Speter 166251876Speter nrow = 2 167251876Speter ncolumn = 3 168251876Speter result[0] = "employee_name" 169251876Speter result[1] = "login" 170251876Speter result[2] = "host" 171251876Speter result[3] = "dummy" 172251876Speter result[4] = "No such user" 173251876Speter result[5] = 0 174251876Speter result[6] = "D. Richard Hipp" 175251876Speter result[7] = "drh" 176251876Speter result[8] = "zadok" 177251876Speter */ 178251876Speter 179251876Speter row->data = res->res + res->sz + (res->sz * row->n); 180251876Speter 181251876Speter return 0; 182251876Speter} 183251876Speter 184251876Speterstatic const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n) 185251876Speter{ 186251876Speter if ((n < 0) || (n >= row->res->sz)) { 187251876Speter return NULL; 188251876Speter } 189251876Speter 190251876Speter return row->data[n]; 191251876Speter} 192251876Speter 193251876Speterstatic apr_status_t dbd_sqlite_datum_get(const apr_dbd_row_t *row, int n, 194251876Speter apr_dbd_type_e type, void *data) 195251876Speter{ 196251876Speter if ((n < 0) || (n >= row->res->sz)) { 197251876Speter return APR_EGENERAL; 198251876Speter } 199251876Speter 200251876Speter if (row->data[n] == NULL) { 201251876Speter return APR_ENOENT; 202251876Speter } 203251876Speter 204251876Speter switch (type) { 205251876Speter case APR_DBD_TYPE_TINY: 206251876Speter *(char*)data = atoi(row->data[n]); 207251876Speter break; 208251876Speter case APR_DBD_TYPE_UTINY: 209251876Speter *(unsigned char*)data = atoi(row->data[n]); 210251876Speter break; 211251876Speter case APR_DBD_TYPE_SHORT: 212251876Speter *(short*)data = atoi(row->data[n]); 213251876Speter break; 214251876Speter case APR_DBD_TYPE_USHORT: 215251876Speter *(unsigned short*)data = atoi(row->data[n]); 216251876Speter break; 217251876Speter case APR_DBD_TYPE_INT: 218251876Speter *(int*)data = atoi(row->data[n]); 219251876Speter break; 220251876Speter case APR_DBD_TYPE_UINT: 221251876Speter *(unsigned int*)data = atoi(row->data[n]); 222251876Speter break; 223251876Speter case APR_DBD_TYPE_LONG: 224251876Speter *(long*)data = atol(row->data[n]); 225251876Speter break; 226251876Speter case APR_DBD_TYPE_ULONG: 227251876Speter *(unsigned long*)data = atol(row->data[n]); 228251876Speter break; 229251876Speter case APR_DBD_TYPE_LONGLONG: 230251876Speter *(apr_int64_t*)data = apr_atoi64(row->data[n]); 231251876Speter break; 232251876Speter case APR_DBD_TYPE_ULONGLONG: 233251876Speter *(apr_uint64_t*)data = apr_atoi64(row->data[n]); 234251876Speter break; 235251876Speter case APR_DBD_TYPE_FLOAT: 236251876Speter *(float*)data = atof(row->data[n]); 237251876Speter break; 238251876Speter case APR_DBD_TYPE_DOUBLE: 239251876Speter *(double*)data = atof(row->data[n]); 240251876Speter break; 241251876Speter case APR_DBD_TYPE_STRING: 242251876Speter case APR_DBD_TYPE_TEXT: 243251876Speter case APR_DBD_TYPE_TIME: 244251876Speter case APR_DBD_TYPE_DATE: 245251876Speter case APR_DBD_TYPE_DATETIME: 246251876Speter case APR_DBD_TYPE_TIMESTAMP: 247251876Speter case APR_DBD_TYPE_ZTIMESTAMP: 248251876Speter *(char**)data = row->data[n]; 249251876Speter break; 250251876Speter case APR_DBD_TYPE_BLOB: 251251876Speter case APR_DBD_TYPE_CLOB: 252251876Speter { 253251876Speter apr_bucket *e; 254251876Speter apr_bucket_brigade *b = (apr_bucket_brigade*)data; 255251876Speter 256251876Speter e = apr_bucket_pool_create(row->data[n],strlen(row->data[n]), 257251876Speter row->res->pool, b->bucket_alloc); 258251876Speter APR_BRIGADE_INSERT_TAIL(b, e); 259251876Speter } 260251876Speter break; 261251876Speter case APR_DBD_TYPE_NULL: 262251876Speter *(void**)data = NULL; 263251876Speter break; 264251876Speter default: 265251876Speter return APR_EGENERAL; 266251876Speter } 267251876Speter 268251876Speter return APR_SUCCESS; 269251876Speter} 270251876Speter 271251876Speterstatic const char *dbd_sqlite_error(apr_dbd_t * sql, int n) 272251876Speter{ 273251876Speter return sql->errmsg; 274251876Speter} 275251876Speter 276251876Speterstatic int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query) 277251876Speter{ 278251876Speter char **result; 279251876Speter int ret; 280251876Speter int tuples = 0; 281251876Speter int fields = 0; 282251876Speter 283251876Speter if (sql->trans && sql->trans->errnum) { 284251876Speter return sql->trans->errnum; 285251876Speter } 286251876Speter 287251876Speter FREE_ERROR_MSG(sql); 288251876Speter 289251876Speter ret = 290251876Speter sqlite_get_table(sql->conn, query, &result, &tuples, &fields, 291251876Speter &sql->errmsg); 292251876Speter if (ret == SQLITE_OK) { 293251876Speter *nrows = sqlite_changes(sql->conn); 294251876Speter 295251876Speter if (tuples > 0) 296251876Speter free(result); 297251876Speter 298251876Speter ret = 0; 299251876Speter } 300251876Speter 301251876Speter if (TXN_NOTICE_ERRORS(sql->trans)) { 302251876Speter sql->trans->errnum = ret; 303251876Speter } 304251876Speter 305251876Speter return ret; 306251876Speter} 307251876Speter 308251876Speterstatic apr_status_t free_mem(void *data) 309251876Speter{ 310251876Speter sqlite_freemem(data); 311251876Speter return APR_SUCCESS; 312251876Speter} 313251876Speter 314251876Speterstatic const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg, 315251876Speter apr_dbd_t * sql) 316251876Speter{ 317251876Speter char *ret = sqlite_mprintf("%q", arg); 318251876Speter apr_pool_cleanup_register(pool, ret, free_mem, apr_pool_cleanup_null); 319251876Speter return ret; 320251876Speter} 321251876Speter 322251876Speterstatic int dbd_sqlite_prepare(apr_pool_t * pool, apr_dbd_t * sql, 323251876Speter const char *query, const char *label, 324251876Speter int nargs, int nvals, apr_dbd_type_e *types, 325251876Speter apr_dbd_prepared_t ** statement) 326251876Speter{ 327251876Speter return APR_ENOTIMPL; 328251876Speter} 329251876Speter 330251876Speterstatic int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql, 331251876Speter int *nrows, apr_dbd_prepared_t * statement, 332251876Speter const char **values) 333251876Speter{ 334251876Speter return APR_ENOTIMPL; 335251876Speter} 336251876Speter 337251876Speterstatic int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql, 338251876Speter int *nrows, apr_dbd_prepared_t * statement, 339251876Speter va_list args) 340251876Speter{ 341251876Speter return APR_ENOTIMPL; 342251876Speter} 343251876Speter 344251876Speterstatic int dbd_sqlite_pselect(apr_pool_t * pool, apr_dbd_t * sql, 345251876Speter apr_dbd_results_t ** results, 346251876Speter apr_dbd_prepared_t * statement, 347251876Speter int seek, const char **values) 348251876Speter{ 349251876Speter return APR_ENOTIMPL; 350251876Speter} 351251876Speter 352251876Speterstatic int dbd_sqlite_pvselect(apr_pool_t * pool, apr_dbd_t * sql, 353251876Speter apr_dbd_results_t ** results, 354251876Speter apr_dbd_prepared_t * statement, int seek, 355251876Speter va_list args) 356251876Speter{ 357251876Speter return APR_ENOTIMPL; 358251876Speter} 359251876Speter 360251876Speterstatic int dbd_sqlite_pbquery(apr_pool_t * pool, apr_dbd_t * sql, 361251876Speter int *nrows, apr_dbd_prepared_t * statement, 362251876Speter const void **values) 363251876Speter{ 364251876Speter return APR_ENOTIMPL; 365251876Speter} 366251876Speter 367251876Speterstatic int dbd_sqlite_pvbquery(apr_pool_t * pool, apr_dbd_t * sql, 368251876Speter int *nrows, apr_dbd_prepared_t * statement, 369251876Speter va_list args) 370251876Speter{ 371251876Speter return APR_ENOTIMPL; 372251876Speter} 373251876Speter 374251876Speterstatic int dbd_sqlite_pbselect(apr_pool_t * pool, apr_dbd_t * sql, 375251876Speter apr_dbd_results_t ** results, 376251876Speter apr_dbd_prepared_t * statement, 377251876Speter int seek, const void **values) 378251876Speter{ 379251876Speter return APR_ENOTIMPL; 380251876Speter} 381251876Speter 382251876Speterstatic int dbd_sqlite_pvbselect(apr_pool_t * pool, apr_dbd_t * sql, 383251876Speter apr_dbd_results_t ** results, 384251876Speter apr_dbd_prepared_t * statement, int seek, 385251876Speter va_list args) 386251876Speter{ 387251876Speter return APR_ENOTIMPL; 388251876Speter} 389251876Speter 390251876Speterstatic int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle, 391251876Speter apr_dbd_transaction_t ** trans) 392251876Speter{ 393251876Speter int ret, rows; 394251876Speter 395251876Speter ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION"); 396251876Speter if (ret == 0) { 397251876Speter if (!*trans) { 398251876Speter *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t)); 399251876Speter } 400251876Speter (*trans)->handle = handle; 401251876Speter handle->trans = *trans; 402251876Speter } 403251876Speter else { 404251876Speter ret = -1; 405251876Speter } 406251876Speter return ret; 407251876Speter} 408251876Speter 409251876Speterstatic int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans) 410251876Speter{ 411251876Speter int rows; 412251876Speter int ret = -1; /* no transaction is an error cond */ 413251876Speter 414251876Speter if (trans) { 415251876Speter /* rollback on error or explicit rollback request */ 416251876Speter if (trans->errnum || TXN_DO_ROLLBACK(trans)) { 417251876Speter trans->errnum = 0; 418251876Speter ret = 419251876Speter dbd_sqlite_query(trans->handle, &rows, 420251876Speter "ROLLBACK TRANSACTION"); 421251876Speter } 422251876Speter else { 423251876Speter ret = 424251876Speter dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION"); 425251876Speter } 426251876Speter trans->handle->trans = NULL; 427251876Speter } 428251876Speter 429251876Speter return ret; 430251876Speter} 431251876Speter 432251876Speterstatic int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans) 433251876Speter{ 434251876Speter if (!trans) 435251876Speter return APR_DBD_TRANSACTION_COMMIT; 436251876Speter 437251876Speter return trans->mode; 438251876Speter} 439251876Speter 440251876Speterstatic int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans, 441251876Speter int mode) 442251876Speter{ 443251876Speter if (!trans) 444251876Speter return APR_DBD_TRANSACTION_COMMIT; 445251876Speter 446251876Speter return trans->mode = (mode & TXN_MODE_BITS); 447251876Speter} 448251876Speter 449251876Speterstatic apr_status_t error_free(void *data) 450251876Speter{ 451251876Speter free(data); 452251876Speter return APR_SUCCESS; 453251876Speter} 454251876Speter 455251876Speterstatic apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_, 456251876Speter const char **error) 457251876Speter{ 458251876Speter apr_dbd_t *sql; 459251876Speter sqlite *conn = NULL; 460251876Speter char *perm; 461251876Speter int iperms = 600; 462251876Speter char* params = apr_pstrdup(pool, params_); 463251876Speter /* params = "[filename]:[permissions]" 464251876Speter * example: "shopping.db:600" 465251876Speter */ 466251876Speter 467251876Speter perm = strstr(params, ":"); 468251876Speter if (perm) { 469251876Speter *(perm++) = '\x00'; /* split the filename and permissions */ 470251876Speter 471251876Speter if (strlen(perm) > 0) 472251876Speter iperms = atoi(perm); 473251876Speter } 474251876Speter 475251876Speter if (error) { 476251876Speter *error = NULL; 477251876Speter 478251876Speter conn = sqlite_open(params, iperms, (char **)error); 479251876Speter 480251876Speter if (*error) { 481251876Speter apr_pool_cleanup_register(pool, *error, error_free, 482251876Speter apr_pool_cleanup_null); 483251876Speter } 484251876Speter } 485251876Speter else { 486251876Speter conn = sqlite_open(params, iperms, NULL); 487251876Speter } 488251876Speter 489251876Speter sql = apr_pcalloc(pool, sizeof(*sql)); 490251876Speter sql->conn = conn; 491251876Speter 492251876Speter return sql; 493251876Speter} 494251876Speter 495251876Speterstatic apr_status_t dbd_sqlite_close(apr_dbd_t * handle) 496251876Speter{ 497251876Speter if (handle->conn) { 498251876Speter sqlite_close(handle->conn); 499251876Speter handle->conn = NULL; 500251876Speter } 501251876Speter return APR_SUCCESS; 502251876Speter} 503251876Speter 504251876Speterstatic apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool, 505251876Speter apr_dbd_t * handle) 506251876Speter{ 507251876Speter if (handle->conn == NULL) 508251876Speter return -1; 509251876Speter return APR_SUCCESS; 510251876Speter} 511251876Speter 512251876Speterstatic int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle, 513251876Speter const char *name) 514251876Speter{ 515251876Speter return APR_ENOTIMPL; 516251876Speter} 517251876Speter 518251876Speterstatic void *dbd_sqlite_native(apr_dbd_t * handle) 519251876Speter{ 520251876Speter return handle->conn; 521251876Speter} 522251876Speter 523251876Speterstatic int dbd_sqlite_num_cols(apr_dbd_results_t * res) 524251876Speter{ 525251876Speter return res->sz; 526251876Speter} 527251876Speter 528251876Speterstatic int dbd_sqlite_num_tuples(apr_dbd_results_t * res) 529251876Speter{ 530251876Speter return res->ntuples; 531251876Speter} 532251876Speter 533251876SpeterAPU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = { 534251876Speter "sqlite2", 535251876Speter NULL, 536251876Speter dbd_sqlite_native, 537251876Speter dbd_sqlite_open, 538251876Speter dbd_sqlite_check_conn, 539251876Speter dbd_sqlite_close, 540251876Speter dbd_sqlite_select_db, 541251876Speter dbd_sqlite_start_transaction, 542251876Speter dbd_sqlite_end_transaction, 543251876Speter dbd_sqlite_query, 544251876Speter dbd_sqlite_select, 545251876Speter dbd_sqlite_num_cols, 546251876Speter dbd_sqlite_num_tuples, 547251876Speter dbd_sqlite_get_row, 548251876Speter dbd_sqlite_get_entry, 549251876Speter dbd_sqlite_error, 550251876Speter dbd_sqlite_escape, 551251876Speter dbd_sqlite_prepare, 552251876Speter dbd_sqlite_pvquery, 553251876Speter dbd_sqlite_pvselect, 554251876Speter dbd_sqlite_pquery, 555251876Speter dbd_sqlite_pselect, 556251876Speter dbd_sqlite_get_name, 557251876Speter dbd_sqlite_transaction_mode_get, 558251876Speter dbd_sqlite_transaction_mode_set, 559251876Speter NULL, 560251876Speter dbd_sqlite_pvbquery, 561251876Speter dbd_sqlite_pvbselect, 562251876Speter dbd_sqlite_pbquery, 563251876Speter dbd_sqlite_pbselect, 564251876Speter dbd_sqlite_datum_get 565251876Speter}; 566251876Speter#endif 567