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_SQLITE3 20251876Speter 21251876Speter#include <ctype.h> 22251876Speter#include <stdlib.h> 23251876Speter 24251876Speter#include <sqlite3.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 32251876Speter#define MAX_RETRY_COUNT 15 33251876Speter#define MAX_RETRY_SLEEP 100000 34251876Speter 35251876Speterstruct apr_dbd_transaction_t { 36251876Speter int mode; 37251876Speter int errnum; 38251876Speter apr_dbd_t *handle; 39251876Speter}; 40251876Speter 41251876Speterstruct apr_dbd_t { 42251876Speter sqlite3 *conn; 43251876Speter apr_dbd_transaction_t *trans; 44251876Speter apr_pool_t *pool; 45251876Speter apr_dbd_prepared_t *prep; 46251876Speter}; 47251876Speter 48251876Spetertypedef struct { 49251876Speter char *name; 50251876Speter char *value; 51251876Speter int size; 52251876Speter int type; 53251876Speter} apr_dbd_column_t; 54251876Speter 55251876Speterstruct apr_dbd_row_t { 56251876Speter apr_dbd_results_t *res; 57251876Speter apr_dbd_column_t **columns; 58251876Speter apr_dbd_row_t *next_row; 59251876Speter int columnCount; 60251876Speter int rownum; 61251876Speter}; 62251876Speter 63251876Speterstruct apr_dbd_results_t { 64251876Speter int random; 65251876Speter sqlite3 *handle; 66251876Speter sqlite3_stmt *stmt; 67251876Speter apr_dbd_row_t *next_row; 68251876Speter size_t sz; 69251876Speter int tuples; 70251876Speter char **col_names; 71251876Speter apr_pool_t *pool; 72251876Speter}; 73251876Speter 74251876Speterstruct apr_dbd_prepared_t { 75251876Speter sqlite3_stmt *stmt; 76251876Speter apr_dbd_prepared_t *next; 77251876Speter int nargs; 78251876Speter int nvals; 79251876Speter apr_dbd_type_e *types; 80251876Speter}; 81251876Speter 82251876Speter#define dbd_sqlite3_is_success(x) (((x) == SQLITE_DONE) || ((x) == SQLITE_OK)) 83251876Speter 84251876Speterstatic int dbd_sqlite3_select_internal(apr_pool_t *pool, 85251876Speter apr_dbd_t *sql, 86251876Speter apr_dbd_results_t **results, 87251876Speter sqlite3_stmt *stmt, int seek) 88251876Speter{ 89251876Speter int ret, retry_count = 0, column_count; 90251876Speter size_t i, num_tuples = 0; 91251876Speter int increment = 0; 92251876Speter apr_dbd_row_t *row = NULL; 93251876Speter apr_dbd_row_t *lastrow = NULL; 94251876Speter apr_dbd_column_t *column; 95251876Speter char *hold = NULL; 96251876Speter 97251876Speter column_count = sqlite3_column_count(stmt); 98251876Speter if (!*results) { 99251876Speter *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t)); 100251876Speter } 101251876Speter (*results)->stmt = stmt; 102251876Speter (*results)->sz = column_count; 103251876Speter (*results)->random = seek; 104251876Speter (*results)->next_row = 0; 105251876Speter (*results)->tuples = 0; 106251876Speter (*results)->col_names = apr_pcalloc(pool, column_count * sizeof(char *)); 107251876Speter (*results)->pool = pool; 108251876Speter do { 109251876Speter ret = sqlite3_step(stmt); 110251876Speter if (ret == SQLITE_BUSY) { 111251876Speter if (retry_count++ > MAX_RETRY_COUNT) { 112251876Speter ret = SQLITE_ERROR; 113251876Speter } else { 114251876Speter apr_dbd_mutex_unlock(); 115251876Speter apr_sleep(MAX_RETRY_SLEEP); 116251876Speter apr_dbd_mutex_lock(); 117251876Speter } 118251876Speter } else if (ret == SQLITE_ROW) { 119251876Speter int length; 120251876Speter row = apr_palloc(pool, sizeof(apr_dbd_row_t)); 121251876Speter row->res = *results; 122251876Speter increment = sizeof(apr_dbd_column_t *); 123251876Speter length = increment * (*results)->sz; 124251876Speter row->columns = apr_palloc(pool, length); 125251876Speter row->columnCount = column_count; 126251876Speter for (i = 0; i < (*results)->sz; i++) { 127251876Speter column = apr_palloc(pool, sizeof(apr_dbd_column_t)); 128251876Speter row->columns[i] = column; 129251876Speter /* copy column name once only */ 130251876Speter if ((*results)->col_names[i] == NULL) { 131251876Speter (*results)->col_names[i] = 132251876Speter apr_pstrdup(pool, sqlite3_column_name(stmt, i)); 133251876Speter } 134251876Speter column->name = (*results)->col_names[i]; 135251876Speter column->size = sqlite3_column_bytes(stmt, i); 136251876Speter column->type = sqlite3_column_type(stmt, i); 137251876Speter column->value = NULL; 138251876Speter switch (column->type) { 139251876Speter case SQLITE_FLOAT: 140251876Speter case SQLITE_INTEGER: 141251876Speter case SQLITE_TEXT: 142251876Speter hold = (char *) sqlite3_column_text(stmt, i); 143251876Speter if (hold) { 144251876Speter column->value = apr_pstrmemdup(pool, hold, 145251876Speter column->size); 146251876Speter } 147251876Speter break; 148251876Speter case SQLITE_BLOB: 149251876Speter hold = (char *) sqlite3_column_blob(stmt, i); 150251876Speter if (hold) { 151251876Speter column->value = apr_pstrmemdup(pool, hold, 152251876Speter column->size); 153251876Speter } 154251876Speter break; 155251876Speter case SQLITE_NULL: 156251876Speter break; 157251876Speter } 158251876Speter } 159251876Speter row->rownum = num_tuples++; 160251876Speter row->next_row = 0; 161251876Speter (*results)->tuples = num_tuples; 162251876Speter if ((*results)->next_row == 0) { 163251876Speter (*results)->next_row = row; 164251876Speter } 165251876Speter if (lastrow != 0) { 166251876Speter lastrow->next_row = row; 167251876Speter } 168251876Speter lastrow = row; 169251876Speter } 170251876Speter } while (ret == SQLITE_ROW || ret == SQLITE_BUSY); 171251876Speter 172251876Speter if (dbd_sqlite3_is_success(ret)) { 173251876Speter ret = 0; 174251876Speter } 175251876Speter return ret; 176251876Speter} 177251876Speter 178251876Speterstatic int dbd_sqlite3_select(apr_pool_t *pool, apr_dbd_t *sql, 179251876Speter apr_dbd_results_t **results, const char *query, 180251876Speter int seek) 181251876Speter{ 182251876Speter sqlite3_stmt *stmt = NULL; 183251876Speter const char *tail = NULL; 184251876Speter int ret; 185251876Speter 186251876Speter if (sql->trans && sql->trans->errnum) { 187251876Speter return sql->trans->errnum; 188251876Speter } 189251876Speter 190251876Speter apr_dbd_mutex_lock(); 191251876Speter 192251876Speter ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail); 193251876Speter if (dbd_sqlite3_is_success(ret)) { 194251876Speter ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek); 195251876Speter } 196251876Speter sqlite3_finalize(stmt); 197251876Speter 198251876Speter apr_dbd_mutex_unlock(); 199251876Speter 200251876Speter if (TXN_NOTICE_ERRORS(sql->trans)) { 201251876Speter sql->trans->errnum = ret; 202251876Speter } 203251876Speter return ret; 204251876Speter} 205251876Speter 206251876Speterstatic const char *dbd_sqlite3_get_name(const apr_dbd_results_t *res, int n) 207251876Speter{ 208251876Speter if ((n < 0) || ((size_t)n >= res->sz)) { 209251876Speter return NULL; 210251876Speter } 211251876Speter 212251876Speter return res->col_names[n]; 213251876Speter} 214251876Speter 215251876Speterstatic int dbd_sqlite3_get_row(apr_pool_t *pool, apr_dbd_results_t *res, 216251876Speter apr_dbd_row_t **rowp, int rownum) 217251876Speter{ 218251876Speter int i = 0; 219251876Speter 220251876Speter if (rownum == -1) { 221251876Speter *rowp = res->next_row; 222251876Speter if (*rowp == 0) 223251876Speter return -1; 224251876Speter res->next_row = (*rowp)->next_row; 225251876Speter return 0; 226251876Speter } 227251876Speter if (rownum > res->tuples) { 228251876Speter return -1; 229251876Speter } 230251876Speter rownum--; 231251876Speter *rowp = res->next_row; 232251876Speter for (; *rowp != 0; i++, *rowp = (*rowp)->next_row) { 233251876Speter if (i == rownum) { 234251876Speter return 0; 235251876Speter } 236251876Speter } 237251876Speter 238251876Speter return -1; 239251876Speter 240251876Speter} 241251876Speter 242251876Speterstatic const char *dbd_sqlite3_get_entry(const apr_dbd_row_t *row, int n) 243251876Speter{ 244251876Speter apr_dbd_column_t *column; 245251876Speter const char *value; 246251876Speter if ((n < 0) || (n >= row->columnCount)) { 247251876Speter return NULL; 248251876Speter } 249251876Speter column = row->columns[n]; 250251876Speter value = column->value; 251251876Speter return value; 252251876Speter} 253251876Speter 254251876Speterstatic apr_status_t dbd_sqlite3_datum_get(const apr_dbd_row_t *row, int n, 255251876Speter apr_dbd_type_e type, void *data) 256251876Speter{ 257251876Speter if ((n < 0) || ((size_t)n >= row->res->sz)) { 258251876Speter return APR_EGENERAL; 259251876Speter } 260251876Speter 261251876Speter if (row->columns[n]->type == SQLITE_NULL) { 262251876Speter return APR_ENOENT; 263251876Speter } 264251876Speter 265251876Speter switch (type) { 266251876Speter case APR_DBD_TYPE_TINY: 267251876Speter *(char*)data = atoi(row->columns[n]->value); 268251876Speter break; 269251876Speter case APR_DBD_TYPE_UTINY: 270251876Speter *(unsigned char*)data = atoi(row->columns[n]->value); 271251876Speter break; 272251876Speter case APR_DBD_TYPE_SHORT: 273251876Speter *(short*)data = atoi(row->columns[n]->value); 274251876Speter break; 275251876Speter case APR_DBD_TYPE_USHORT: 276251876Speter *(unsigned short*)data = atoi(row->columns[n]->value); 277251876Speter break; 278251876Speter case APR_DBD_TYPE_INT: 279251876Speter *(int*)data = atoi(row->columns[n]->value); 280251876Speter break; 281251876Speter case APR_DBD_TYPE_UINT: 282251876Speter *(unsigned int*)data = atoi(row->columns[n]->value); 283251876Speter break; 284251876Speter case APR_DBD_TYPE_LONG: 285251876Speter *(long*)data = atol(row->columns[n]->value); 286251876Speter break; 287251876Speter case APR_DBD_TYPE_ULONG: 288251876Speter *(unsigned long*)data = atol(row->columns[n]->value); 289251876Speter break; 290251876Speter case APR_DBD_TYPE_LONGLONG: 291251876Speter *(apr_int64_t*)data = apr_atoi64(row->columns[n]->value); 292251876Speter break; 293251876Speter case APR_DBD_TYPE_ULONGLONG: 294251876Speter *(apr_uint64_t*)data = apr_atoi64(row->columns[n]->value); 295251876Speter break; 296251876Speter case APR_DBD_TYPE_FLOAT: 297251876Speter *(float*)data = (float)atof(row->columns[n]->value); 298251876Speter break; 299251876Speter case APR_DBD_TYPE_DOUBLE: 300251876Speter *(double*)data = atof(row->columns[n]->value); 301251876Speter break; 302251876Speter case APR_DBD_TYPE_STRING: 303251876Speter case APR_DBD_TYPE_TEXT: 304251876Speter case APR_DBD_TYPE_TIME: 305251876Speter case APR_DBD_TYPE_DATE: 306251876Speter case APR_DBD_TYPE_DATETIME: 307251876Speter case APR_DBD_TYPE_TIMESTAMP: 308251876Speter case APR_DBD_TYPE_ZTIMESTAMP: 309251876Speter *(char**)data = row->columns[n]->value; 310251876Speter break; 311251876Speter case APR_DBD_TYPE_BLOB: 312251876Speter case APR_DBD_TYPE_CLOB: 313251876Speter { 314251876Speter apr_bucket *e; 315251876Speter apr_bucket_brigade *b = (apr_bucket_brigade*)data; 316251876Speter 317251876Speter e = apr_bucket_pool_create(row->columns[n]->value, 318251876Speter row->columns[n]->size, 319251876Speter row->res->pool, b->bucket_alloc); 320251876Speter APR_BRIGADE_INSERT_TAIL(b, e); 321251876Speter } 322251876Speter break; 323251876Speter case APR_DBD_TYPE_NULL: 324251876Speter *(void**)data = NULL; 325251876Speter break; 326251876Speter default: 327251876Speter return APR_EGENERAL; 328251876Speter } 329251876Speter 330251876Speter return APR_SUCCESS; 331251876Speter} 332251876Speter 333251876Speterstatic const char *dbd_sqlite3_error(apr_dbd_t *sql, int n) 334251876Speter{ 335251876Speter return sqlite3_errmsg(sql->conn); 336251876Speter} 337251876Speter 338251876Speterstatic int dbd_sqlite3_query_internal(apr_dbd_t *sql, sqlite3_stmt *stmt, 339251876Speter int *nrows) 340251876Speter{ 341251876Speter int ret = -1, retry_count = 0; 342251876Speter 343251876Speter while(retry_count++ <= MAX_RETRY_COUNT) { 344251876Speter ret = sqlite3_step(stmt); 345251876Speter if (ret != SQLITE_BUSY) 346251876Speter break; 347251876Speter 348251876Speter apr_dbd_mutex_unlock(); 349251876Speter apr_sleep(MAX_RETRY_SLEEP); 350251876Speter apr_dbd_mutex_lock(); 351251876Speter } 352251876Speter 353251876Speter *nrows = sqlite3_changes(sql->conn); 354251876Speter 355251876Speter if (dbd_sqlite3_is_success(ret)) { 356251876Speter ret = 0; 357251876Speter } 358251876Speter return ret; 359251876Speter} 360251876Speter 361251876Speterstatic int dbd_sqlite3_query(apr_dbd_t *sql, int *nrows, const char *query) 362251876Speter{ 363251876Speter sqlite3_stmt *stmt = NULL; 364251876Speter const char *tail = NULL; 365251876Speter int ret = -1, length = 0; 366251876Speter 367251876Speter if (sql->trans && sql->trans->errnum) { 368251876Speter return sql->trans->errnum; 369251876Speter } 370251876Speter 371251876Speter length = strlen(query); 372251876Speter apr_dbd_mutex_lock(); 373251876Speter 374251876Speter do { 375251876Speter ret = sqlite3_prepare(sql->conn, query, length, &stmt, &tail); 376251876Speter if (ret != SQLITE_OK) { 377251876Speter sqlite3_finalize(stmt); 378251876Speter break; 379251876Speter } 380251876Speter 381251876Speter ret = dbd_sqlite3_query_internal(sql, stmt, nrows); 382251876Speter 383251876Speter sqlite3_finalize(stmt); 384251876Speter length -= (tail - query); 385251876Speter query = tail; 386251876Speter } while (length > 0); 387251876Speter 388251876Speter apr_dbd_mutex_unlock(); 389251876Speter 390251876Speter if (TXN_NOTICE_ERRORS(sql->trans)) { 391251876Speter sql->trans->errnum = ret; 392251876Speter } 393251876Speter return ret; 394251876Speter} 395251876Speter 396251876Speterstatic apr_status_t free_mem(void *data) 397251876Speter{ 398251876Speter sqlite3_free(data); 399251876Speter return APR_SUCCESS; 400251876Speter} 401251876Speter 402251876Speterstatic const char *dbd_sqlite3_escape(apr_pool_t *pool, const char *arg, 403251876Speter apr_dbd_t *sql) 404251876Speter{ 405251876Speter char *ret = sqlite3_mprintf("%q", arg); 406251876Speter apr_pool_cleanup_register(pool, ret, free_mem, 407251876Speter apr_pool_cleanup_null); 408251876Speter return ret; 409251876Speter} 410251876Speter 411251876Speterstatic int dbd_sqlite3_prepare(apr_pool_t *pool, apr_dbd_t *sql, 412251876Speter const char *query, const char *label, 413251876Speter int nargs, int nvals, apr_dbd_type_e *types, 414251876Speter apr_dbd_prepared_t **statement) 415251876Speter{ 416251876Speter sqlite3_stmt *stmt; 417251876Speter const char *tail = NULL; 418251876Speter int ret; 419251876Speter 420251876Speter apr_dbd_mutex_lock(); 421251876Speter 422251876Speter ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail); 423251876Speter if (ret == SQLITE_OK) { 424251876Speter apr_dbd_prepared_t *prep; 425251876Speter 426251876Speter prep = apr_pcalloc(sql->pool, sizeof(*prep)); 427251876Speter prep->stmt = stmt; 428251876Speter prep->next = sql->prep; 429251876Speter prep->nargs = nargs; 430251876Speter prep->nvals = nvals; 431251876Speter prep->types = types; 432251876Speter 433251876Speter /* link new statement to the handle */ 434251876Speter sql->prep = prep; 435251876Speter 436251876Speter *statement = prep; 437251876Speter } else { 438251876Speter sqlite3_finalize(stmt); 439251876Speter } 440251876Speter 441251876Speter apr_dbd_mutex_unlock(); 442251876Speter 443251876Speter return ret; 444251876Speter} 445251876Speter 446251876Speterstatic void dbd_sqlite3_bind(apr_dbd_prepared_t *statement, const char **values) 447251876Speter{ 448251876Speter sqlite3_stmt *stmt = statement->stmt; 449251876Speter int i, j; 450251876Speter 451251876Speter for (i = 0, j = 0; i < statement->nargs; i++, j++) { 452251876Speter if (values[j] == NULL) { 453251876Speter sqlite3_bind_null(stmt, i + 1); 454251876Speter } 455251876Speter else { 456251876Speter switch (statement->types[i]) { 457251876Speter case APR_DBD_TYPE_BLOB: 458251876Speter case APR_DBD_TYPE_CLOB: 459251876Speter { 460251876Speter char *data = (char *)values[j]; 461251876Speter int size = atoi((char*)values[++j]); 462251876Speter 463251876Speter /* skip table and column */ 464251876Speter j += 2; 465251876Speter 466251876Speter sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC); 467251876Speter } 468251876Speter break; 469251876Speter default: 470251876Speter sqlite3_bind_text(stmt, i + 1, values[j], 471251876Speter strlen(values[j]), SQLITE_STATIC); 472251876Speter break; 473251876Speter } 474251876Speter } 475251876Speter } 476251876Speter 477251876Speter return; 478251876Speter} 479251876Speter 480251876Speterstatic int dbd_sqlite3_pquery(apr_pool_t *pool, apr_dbd_t *sql, 481251876Speter int *nrows, apr_dbd_prepared_t *statement, 482251876Speter const char **values) 483251876Speter{ 484251876Speter sqlite3_stmt *stmt = statement->stmt; 485251876Speter int ret = -1; 486251876Speter 487251876Speter if (sql->trans && sql->trans->errnum) { 488251876Speter return sql->trans->errnum; 489251876Speter } 490251876Speter 491251876Speter apr_dbd_mutex_lock(); 492251876Speter 493251876Speter ret = sqlite3_reset(stmt); 494251876Speter if (ret == SQLITE_OK) { 495251876Speter dbd_sqlite3_bind(statement, values); 496251876Speter 497251876Speter ret = dbd_sqlite3_query_internal(sql, stmt, nrows); 498251876Speter 499251876Speter sqlite3_reset(stmt); 500251876Speter } 501251876Speter 502251876Speter apr_dbd_mutex_unlock(); 503251876Speter 504251876Speter if (TXN_NOTICE_ERRORS(sql->trans)) { 505251876Speter sql->trans->errnum = ret; 506251876Speter } 507251876Speter return ret; 508251876Speter} 509251876Speter 510251876Speterstatic int dbd_sqlite3_pvquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows, 511251876Speter apr_dbd_prepared_t *statement, va_list args) 512251876Speter{ 513251876Speter const char **values; 514251876Speter int i; 515251876Speter 516251876Speter if (sql->trans && sql->trans->errnum) { 517251876Speter return sql->trans->errnum; 518251876Speter } 519251876Speter 520251876Speter values = apr_palloc(pool, sizeof(*values) * statement->nvals); 521251876Speter 522251876Speter for (i = 0; i < statement->nvals; i++) { 523251876Speter values[i] = va_arg(args, const char*); 524251876Speter } 525251876Speter 526251876Speter return dbd_sqlite3_pquery(pool, sql, nrows, statement, values); 527251876Speter} 528251876Speter 529251876Speterstatic int dbd_sqlite3_pselect(apr_pool_t *pool, apr_dbd_t *sql, 530251876Speter apr_dbd_results_t **results, 531251876Speter apr_dbd_prepared_t *statement, int seek, 532251876Speter const char **values) 533251876Speter{ 534251876Speter sqlite3_stmt *stmt = statement->stmt; 535251876Speter int ret; 536251876Speter 537251876Speter if (sql->trans && sql->trans->errnum) { 538251876Speter return sql->trans->errnum; 539251876Speter } 540251876Speter 541251876Speter apr_dbd_mutex_lock(); 542251876Speter 543251876Speter ret = sqlite3_reset(stmt); 544251876Speter if (ret == SQLITE_OK) { 545251876Speter dbd_sqlite3_bind(statement, values); 546251876Speter 547251876Speter ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek); 548251876Speter 549251876Speter sqlite3_reset(stmt); 550251876Speter } 551251876Speter 552251876Speter apr_dbd_mutex_unlock(); 553251876Speter 554251876Speter if (TXN_NOTICE_ERRORS(sql->trans)) { 555251876Speter sql->trans->errnum = ret; 556251876Speter } 557251876Speter return ret; 558251876Speter} 559251876Speter 560251876Speterstatic int dbd_sqlite3_pvselect(apr_pool_t *pool, apr_dbd_t *sql, 561251876Speter apr_dbd_results_t **results, 562251876Speter apr_dbd_prepared_t *statement, int seek, 563251876Speter va_list args) 564251876Speter{ 565251876Speter const char **values; 566251876Speter int i; 567251876Speter 568251876Speter if (sql->trans && sql->trans->errnum) { 569251876Speter return sql->trans->errnum; 570251876Speter } 571251876Speter 572251876Speter values = apr_palloc(pool, sizeof(*values) * statement->nvals); 573251876Speter 574251876Speter for (i = 0; i < statement->nvals; i++) { 575251876Speter values[i] = va_arg(args, const char*); 576251876Speter } 577251876Speter 578251876Speter return dbd_sqlite3_pselect(pool, sql, results, statement, seek, values); 579251876Speter} 580251876Speter 581251876Speterstatic void dbd_sqlite3_bbind(apr_dbd_prepared_t * statement, 582251876Speter const void **values) 583251876Speter{ 584251876Speter sqlite3_stmt *stmt = statement->stmt; 585251876Speter int i, j; 586251876Speter apr_dbd_type_e type; 587251876Speter 588251876Speter for (i = 0, j = 0; i < statement->nargs; i++, j++) { 589251876Speter type = (values[j] == NULL ? APR_DBD_TYPE_NULL : statement->types[i]); 590251876Speter 591251876Speter switch (type) { 592251876Speter case APR_DBD_TYPE_TINY: 593251876Speter sqlite3_bind_int(stmt, i + 1, *(char*)values[j]); 594251876Speter break; 595251876Speter case APR_DBD_TYPE_UTINY: 596251876Speter sqlite3_bind_int(stmt, i + 1, *(unsigned char*)values[j]); 597251876Speter break; 598251876Speter case APR_DBD_TYPE_SHORT: 599251876Speter sqlite3_bind_int(stmt, i + 1, *(short*)values[j]); 600251876Speter break; 601251876Speter case APR_DBD_TYPE_USHORT: 602251876Speter sqlite3_bind_int(stmt, i + 1, *(unsigned short*)values[j]); 603251876Speter break; 604251876Speter case APR_DBD_TYPE_INT: 605251876Speter sqlite3_bind_int(stmt, i + 1, *(int*)values[j]); 606251876Speter break; 607251876Speter case APR_DBD_TYPE_UINT: 608251876Speter sqlite3_bind_int(stmt, i + 1, *(unsigned int*)values[j]); 609251876Speter break; 610251876Speter case APR_DBD_TYPE_LONG: 611251876Speter sqlite3_bind_int64(stmt, i + 1, *(long*)values[j]); 612251876Speter break; 613251876Speter case APR_DBD_TYPE_ULONG: 614251876Speter sqlite3_bind_int64(stmt, i + 1, *(unsigned long*)values[j]); 615251876Speter break; 616251876Speter case APR_DBD_TYPE_LONGLONG: 617251876Speter sqlite3_bind_int64(stmt, i + 1, *(apr_int64_t*)values[j]); 618251876Speter break; 619251876Speter case APR_DBD_TYPE_ULONGLONG: 620251876Speter sqlite3_bind_int64(stmt, i + 1, *(apr_uint64_t*)values[j]); 621251876Speter break; 622251876Speter case APR_DBD_TYPE_FLOAT: 623251876Speter sqlite3_bind_double(stmt, i + 1, *(float*)values[j]); 624251876Speter break; 625251876Speter case APR_DBD_TYPE_DOUBLE: 626251876Speter sqlite3_bind_double(stmt, i + 1, *(double*)values[j]); 627251876Speter break; 628251876Speter case APR_DBD_TYPE_STRING: 629251876Speter case APR_DBD_TYPE_TEXT: 630251876Speter case APR_DBD_TYPE_TIME: 631251876Speter case APR_DBD_TYPE_DATE: 632251876Speter case APR_DBD_TYPE_DATETIME: 633251876Speter case APR_DBD_TYPE_TIMESTAMP: 634251876Speter case APR_DBD_TYPE_ZTIMESTAMP: 635251876Speter sqlite3_bind_text(stmt, i + 1, values[j], strlen(values[j]), 636251876Speter SQLITE_STATIC); 637251876Speter break; 638251876Speter case APR_DBD_TYPE_BLOB: 639251876Speter case APR_DBD_TYPE_CLOB: 640251876Speter { 641251876Speter char *data = (char*)values[j]; 642251876Speter apr_size_t size = *(apr_size_t*)values[++j]; 643251876Speter 644251876Speter sqlite3_bind_blob(stmt, i + 1, data, size, SQLITE_STATIC); 645251876Speter 646251876Speter /* skip table and column */ 647251876Speter j += 2; 648251876Speter } 649251876Speter break; 650251876Speter case APR_DBD_TYPE_NULL: 651251876Speter default: 652251876Speter sqlite3_bind_null(stmt, i + 1); 653251876Speter break; 654251876Speter } 655251876Speter } 656251876Speter 657251876Speter return; 658251876Speter} 659251876Speter 660251876Speterstatic int dbd_sqlite3_pbquery(apr_pool_t * pool, apr_dbd_t * sql, 661251876Speter int *nrows, apr_dbd_prepared_t * statement, 662251876Speter const void **values) 663251876Speter{ 664251876Speter sqlite3_stmt *stmt = statement->stmt; 665251876Speter int ret = -1; 666251876Speter 667251876Speter if (sql->trans && sql->trans->errnum) { 668251876Speter return sql->trans->errnum; 669251876Speter } 670251876Speter 671251876Speter apr_dbd_mutex_lock(); 672251876Speter 673251876Speter ret = sqlite3_reset(stmt); 674251876Speter if (ret == SQLITE_OK) { 675251876Speter dbd_sqlite3_bbind(statement, values); 676251876Speter 677251876Speter ret = dbd_sqlite3_query_internal(sql, stmt, nrows); 678251876Speter 679251876Speter sqlite3_reset(stmt); 680251876Speter } 681251876Speter 682251876Speter apr_dbd_mutex_unlock(); 683251876Speter 684251876Speter if (TXN_NOTICE_ERRORS(sql->trans)) { 685251876Speter sql->trans->errnum = ret; 686251876Speter } 687251876Speter return ret; 688251876Speter} 689251876Speter 690251876Speterstatic int dbd_sqlite3_pvbquery(apr_pool_t * pool, apr_dbd_t * sql, 691251876Speter int *nrows, apr_dbd_prepared_t * statement, 692251876Speter va_list args) 693251876Speter{ 694251876Speter const void **values; 695251876Speter int i; 696251876Speter 697251876Speter if (sql->trans && sql->trans->errnum) { 698251876Speter return sql->trans->errnum; 699251876Speter } 700251876Speter 701251876Speter values = apr_palloc(pool, sizeof(*values) * statement->nvals); 702251876Speter 703251876Speter for (i = 0; i < statement->nvals; i++) { 704251876Speter values[i] = va_arg(args, const void*); 705251876Speter } 706251876Speter 707251876Speter return dbd_sqlite3_pbquery(pool, sql, nrows, statement, values); 708251876Speter} 709251876Speter 710251876Speterstatic int dbd_sqlite3_pbselect(apr_pool_t * pool, apr_dbd_t * sql, 711251876Speter apr_dbd_results_t ** results, 712251876Speter apr_dbd_prepared_t * statement, 713251876Speter int seek, const void **values) 714251876Speter{ 715251876Speter sqlite3_stmt *stmt = statement->stmt; 716251876Speter int ret; 717251876Speter 718251876Speter if (sql->trans && sql->trans->errnum) { 719251876Speter return sql->trans->errnum; 720251876Speter } 721251876Speter 722251876Speter apr_dbd_mutex_lock(); 723251876Speter 724251876Speter ret = sqlite3_reset(stmt); 725251876Speter if (ret == SQLITE_OK) { 726251876Speter dbd_sqlite3_bbind(statement, values); 727251876Speter 728251876Speter ret = dbd_sqlite3_select_internal(pool, sql, results, stmt, seek); 729251876Speter 730251876Speter sqlite3_reset(stmt); 731251876Speter } 732251876Speter 733251876Speter apr_dbd_mutex_unlock(); 734251876Speter 735251876Speter if (TXN_NOTICE_ERRORS(sql->trans)) { 736251876Speter sql->trans->errnum = ret; 737251876Speter } 738251876Speter return ret; 739251876Speter} 740251876Speter 741251876Speterstatic int dbd_sqlite3_pvbselect(apr_pool_t * pool, apr_dbd_t * sql, 742251876Speter apr_dbd_results_t ** results, 743251876Speter apr_dbd_prepared_t * statement, int seek, 744251876Speter va_list args) 745251876Speter{ 746251876Speter const void **values; 747251876Speter int i; 748251876Speter 749251876Speter if (sql->trans && sql->trans->errnum) { 750251876Speter return sql->trans->errnum; 751251876Speter } 752251876Speter 753251876Speter values = apr_palloc(pool, sizeof(*values) * statement->nvals); 754251876Speter 755251876Speter for (i = 0; i < statement->nvals; i++) { 756251876Speter values[i] = va_arg(args, const void*); 757251876Speter } 758251876Speter 759251876Speter return dbd_sqlite3_pbselect(pool, sql, results, statement, seek, values); 760251876Speter} 761251876Speter 762251876Speterstatic int dbd_sqlite3_start_transaction(apr_pool_t *pool, 763251876Speter apr_dbd_t *handle, 764251876Speter apr_dbd_transaction_t **trans) 765251876Speter{ 766251876Speter int ret = 0; 767251876Speter int nrows = 0; 768251876Speter 769251876Speter ret = dbd_sqlite3_query(handle, &nrows, "BEGIN IMMEDIATE"); 770251876Speter if (!*trans) { 771251876Speter *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t)); 772251876Speter (*trans)->handle = handle; 773251876Speter handle->trans = *trans; 774251876Speter } 775251876Speter 776251876Speter return ret; 777251876Speter} 778251876Speter 779251876Speterstatic int dbd_sqlite3_end_transaction(apr_dbd_transaction_t *trans) 780251876Speter{ 781251876Speter int ret = -1; /* ending transaction that was never started is an error */ 782251876Speter int nrows = 0; 783251876Speter 784251876Speter if (trans) { 785251876Speter /* rollback on error or explicit rollback request */ 786251876Speter if (trans->errnum || TXN_DO_ROLLBACK(trans)) { 787251876Speter trans->errnum = 0; 788251876Speter ret = dbd_sqlite3_query(trans->handle, &nrows, "ROLLBACK"); 789251876Speter } else { 790251876Speter ret = dbd_sqlite3_query(trans->handle, &nrows, "COMMIT"); 791251876Speter } 792251876Speter trans->handle->trans = NULL; 793251876Speter } 794251876Speter 795251876Speter return ret; 796251876Speter} 797251876Speter 798251876Speterstatic int dbd_sqlite3_transaction_mode_get(apr_dbd_transaction_t *trans) 799251876Speter{ 800251876Speter if (!trans) 801251876Speter return APR_DBD_TRANSACTION_COMMIT; 802251876Speter 803251876Speter return trans->mode; 804251876Speter} 805251876Speter 806251876Speterstatic int dbd_sqlite3_transaction_mode_set(apr_dbd_transaction_t *trans, 807251876Speter int mode) 808251876Speter{ 809251876Speter if (!trans) 810251876Speter return APR_DBD_TRANSACTION_COMMIT; 811251876Speter 812251876Speter return trans->mode = (mode & TXN_MODE_BITS); 813251876Speter} 814251876Speter 815251876Speterstatic apr_dbd_t *dbd_sqlite3_open(apr_pool_t *pool, const char *params, 816251876Speter const char **error) 817251876Speter{ 818251876Speter apr_dbd_t *sql = NULL; 819251876Speter sqlite3 *conn = NULL; 820251876Speter int sqlres; 821251876Speter if (!params) 822251876Speter return NULL; 823251876Speter sqlres = sqlite3_open(params, &conn); 824251876Speter if (sqlres != SQLITE_OK) { 825251876Speter if (error) { 826251876Speter *error = apr_pstrdup(pool, sqlite3_errmsg(conn)); 827251876Speter } 828251876Speter sqlite3_close(conn); 829251876Speter return NULL; 830251876Speter } 831251876Speter /* should we register rand or power functions to the sqlite VM? */ 832251876Speter sql = apr_pcalloc(pool, sizeof(*sql)); 833251876Speter sql->conn = conn; 834251876Speter sql->pool = pool; 835251876Speter sql->trans = NULL; 836251876Speter 837251876Speter return sql; 838251876Speter} 839251876Speter 840251876Speterstatic apr_status_t dbd_sqlite3_close(apr_dbd_t *handle) 841251876Speter{ 842251876Speter apr_dbd_prepared_t *prep = handle->prep; 843251876Speter 844251876Speter /* finalize all prepared statements, or we'll get SQLITE_BUSY on close */ 845251876Speter while (prep) { 846251876Speter sqlite3_finalize(prep->stmt); 847251876Speter prep = prep->next; 848251876Speter } 849251876Speter 850251876Speter sqlite3_close(handle->conn); 851251876Speter return APR_SUCCESS; 852251876Speter} 853251876Speter 854251876Speterstatic apr_status_t dbd_sqlite3_check_conn(apr_pool_t *pool, 855251876Speter apr_dbd_t *handle) 856251876Speter{ 857251876Speter return (handle->conn != NULL) ? APR_SUCCESS : APR_EGENERAL; 858251876Speter} 859251876Speter 860251876Speterstatic int dbd_sqlite3_select_db(apr_pool_t *pool, apr_dbd_t *handle, 861251876Speter const char *name) 862251876Speter{ 863251876Speter return APR_ENOTIMPL; 864251876Speter} 865251876Speter 866251876Speterstatic void *dbd_sqlite3_native(apr_dbd_t *handle) 867251876Speter{ 868251876Speter return handle->conn; 869251876Speter} 870251876Speter 871251876Speterstatic int dbd_sqlite3_num_cols(apr_dbd_results_t *res) 872251876Speter{ 873251876Speter return res->sz; 874251876Speter} 875251876Speter 876251876Speterstatic int dbd_sqlite3_num_tuples(apr_dbd_results_t *res) 877251876Speter{ 878251876Speter return res->tuples; 879251876Speter} 880251876Speter 881251876SpeterAPU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite3_driver = { 882251876Speter "sqlite3", 883251876Speter NULL, 884251876Speter dbd_sqlite3_native, 885251876Speter dbd_sqlite3_open, 886251876Speter dbd_sqlite3_check_conn, 887251876Speter dbd_sqlite3_close, 888251876Speter dbd_sqlite3_select_db, 889251876Speter dbd_sqlite3_start_transaction, 890251876Speter dbd_sqlite3_end_transaction, 891251876Speter dbd_sqlite3_query, 892251876Speter dbd_sqlite3_select, 893251876Speter dbd_sqlite3_num_cols, 894251876Speter dbd_sqlite3_num_tuples, 895251876Speter dbd_sqlite3_get_row, 896251876Speter dbd_sqlite3_get_entry, 897251876Speter dbd_sqlite3_error, 898251876Speter dbd_sqlite3_escape, 899251876Speter dbd_sqlite3_prepare, 900251876Speter dbd_sqlite3_pvquery, 901251876Speter dbd_sqlite3_pvselect, 902251876Speter dbd_sqlite3_pquery, 903251876Speter dbd_sqlite3_pselect, 904251876Speter dbd_sqlite3_get_name, 905251876Speter dbd_sqlite3_transaction_mode_get, 906251876Speter dbd_sqlite3_transaction_mode_set, 907251876Speter "?", 908251876Speter dbd_sqlite3_pvbquery, 909251876Speter dbd_sqlite3_pvbselect, 910251876Speter dbd_sqlite3_pbquery, 911251876Speter dbd_sqlite3_pbselect, 912251876Speter dbd_sqlite3_datum_get 913251876Speter}; 914251876Speter#endif 915