root/ext/pdo_sqlite/sqlite_driver.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _pdo_sqlite_error
  2. pdo_sqlite_fetch_error_func
  3. pdo_sqlite_cleanup_callbacks
  4. sqlite_handle_closer
  5. sqlite_handle_preparer
  6. sqlite_handle_doer
  7. pdo_sqlite_last_insert_id
  8. sqlite_handle_quoter
  9. sqlite_handle_begin
  10. sqlite_handle_commit
  11. sqlite_handle_rollback
  12. pdo_sqlite_get_attribute
  13. pdo_sqlite_set_attr
  14. do_callback
  15. php_sqlite3_func_callback
  16. php_sqlite3_func_step_callback
  17. php_sqlite3_func_final_callback
  18. php_sqlite3_collation_callback
  19. PHP_METHOD
  20. PHP_METHOD
  21. PHP_METHOD
  22. get_driver_methods
  23. pdo_sqlite_request_shutdown
  24. make_filename_safe
  25. authorizer
  26. pdo_sqlite_handle_factory

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 5                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 1997-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Author: Wez Furlong <wez@php.net>                                    |
  16   +----------------------------------------------------------------------+
  17 */
  18 
  19 /* $Id$ */
  20 
  21 #ifdef HAVE_CONFIG_H
  22 #include "config.h"
  23 #endif
  24 
  25 #include "php.h"
  26 #include "php_ini.h"
  27 #include "ext/standard/info.h"
  28 #include "pdo/php_pdo.h"
  29 #include "pdo/php_pdo_driver.h"
  30 #include "php_pdo_sqlite.h"
  31 #include "php_pdo_sqlite_int.h"
  32 #include "zend_exceptions.h"
  33 
  34 int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
  35 {
  36         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
  37         pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
  38         pdo_sqlite_error_info *einfo = &H->einfo;
  39 
  40         einfo->errcode = sqlite3_errcode(H->db);
  41         einfo->file = file;
  42         einfo->line = line;
  43 
  44         if (einfo->errcode != SQLITE_OK) {
  45                 if (einfo->errmsg) {
  46                         pefree(einfo->errmsg, dbh->is_persistent);
  47                 }
  48                 einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
  49         } else { /* no error */
  50                 strncpy(*pdo_err, PDO_ERR_NONE, sizeof(PDO_ERR_NONE));
  51                 return 0;
  52         }
  53         switch (einfo->errcode) {
  54                 case SQLITE_NOTFOUND:
  55                         strncpy(*pdo_err, "42S02", sizeof("42S02"));
  56                         break;  
  57 
  58                 case SQLITE_INTERRUPT:
  59                         strncpy(*pdo_err, "01002", sizeof("01002"));
  60                         break;
  61 
  62                 case SQLITE_NOLFS:
  63                         strncpy(*pdo_err, "HYC00", sizeof("HYC00"));
  64                         break;
  65 
  66                 case SQLITE_TOOBIG:
  67                         strncpy(*pdo_err, "22001", sizeof("22001"));
  68                         break;
  69         
  70                 case SQLITE_CONSTRAINT:
  71                         strncpy(*pdo_err, "23000", sizeof("23000"));
  72                         break;
  73 
  74                 case SQLITE_ERROR:
  75                 default:
  76                         strncpy(*pdo_err, "HY000", sizeof("HY000"));
  77                         break;
  78         }
  79 
  80         if (!dbh->methods) {
  81                 zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
  82                                 *pdo_err, einfo->errcode, einfo->errmsg);
  83         }
  84         
  85         return einfo->errcode;
  86 }
  87 /* }}} */
  88 
  89 static int pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
  90 {
  91         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
  92         pdo_sqlite_error_info *einfo = &H->einfo;
  93 
  94         if (einfo->errcode) {
  95                 add_next_index_long(info, einfo->errcode);
  96                 add_next_index_string(info, einfo->errmsg, 1);
  97         }
  98 
  99         return 1;
 100 }
 101 
 102 static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC)
 103 {
 104         struct pdo_sqlite_func *func;
 105 
 106         while (H->funcs) {
 107                 func = H->funcs;
 108                 H->funcs = func->next;
 109 
 110                 if (H->db) {
 111                         /* delete the function from the handle */
 112                         sqlite3_create_function(H->db,
 113                                 func->funcname,
 114                                 func->argc,
 115                                 SQLITE_UTF8,
 116                                 func,
 117                                 NULL, NULL, NULL);
 118                 }
 119 
 120                 efree((char*)func->funcname);
 121                 if (func->func) {
 122                         zval_ptr_dtor(&func->func);
 123                 }
 124                 if (func->step) {
 125                         zval_ptr_dtor(&func->step);
 126                 }
 127                 if (func->fini) {
 128                         zval_ptr_dtor(&func->fini);
 129                 }
 130                 efree(func);
 131         }
 132 
 133         while (H->collations) {
 134                 struct pdo_sqlite_collation *collation;
 135                 collation = H->collations;
 136                 H->collations = collation->next;
 137 
 138                 if (H->db) {
 139                         /* delete the collation from the handle */
 140                         sqlite3_create_collation(H->db,
 141                                 collation->name,
 142                                 SQLITE_UTF8,
 143                                 collation,
 144                                 NULL);
 145                 }
 146 
 147                 efree((char*)collation->name);
 148                 if (collation->callback) {
 149                         zval_ptr_dtor(&collation->callback);
 150                 }
 151                 efree(collation);
 152         }
 153 }
 154 
 155 static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
 156 {
 157         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 158         
 159         if (H) {
 160                 pdo_sqlite_error_info *einfo = &H->einfo;
 161 
 162                 pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
 163                 if (H->db) {
 164                         sqlite3_close(H->db);
 165                         H->db = NULL;
 166                 }
 167                 if (einfo->errmsg) {
 168                         pefree(einfo->errmsg, dbh->is_persistent);
 169                         einfo->errmsg = NULL;
 170                 }
 171                 pefree(H, dbh->is_persistent);
 172                 dbh->driver_data = NULL;
 173         }
 174         return 0;
 175 }
 176 /* }}} */
 177 
 178 static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
 179 {
 180         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 181         pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
 182         int i;
 183         const char *tail;
 184 
 185         S->H = H;
 186         stmt->driver_data = S;
 187         stmt->methods = &sqlite_stmt_methods;
 188         stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
 189 
 190         if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
 191                 H->einfo.errcode = SQLITE_ERROR;
 192                 pdo_sqlite_error(dbh);
 193                 return 0;
 194         }
 195 
 196         i = sqlite3_prepare(H->db, sql, sql_len, &S->stmt, &tail);
 197         if (i == SQLITE_OK) {
 198                 return 1;
 199         }
 200 
 201         pdo_sqlite_error(dbh);
 202 
 203         return 0;
 204 }
 205 
 206 static long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
 207 {
 208         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 209         char *errmsg = NULL;
 210 
 211         if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
 212                 pdo_sqlite_error(dbh);
 213                 if (errmsg)
 214                         sqlite3_free(errmsg);
 215 
 216                 return -1;
 217         } else {
 218                 return sqlite3_changes(H->db);
 219         }
 220 }
 221 
 222 static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
 223 {
 224         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 225         char *id;
 226         
 227         id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db) TSRMLS_CC);
 228         *len = strlen(id);
 229         return id;
 230 }
 231 
 232 /* NB: doesn't handle binary strings... use prepared stmts for that */
 233 static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype  TSRMLS_DC)
 234 {
 235         *quoted = safe_emalloc(2, unquotedlen, 3);
 236         sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
 237         *quotedlen = strlen(*quoted);
 238         return 1;
 239 }
 240 
 241 static int sqlite_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
 242 {
 243         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 244         char *errmsg = NULL;
 245 
 246         if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
 247                 pdo_sqlite_error(dbh);
 248                 if (errmsg)
 249                         sqlite3_free(errmsg);
 250                 return 0;
 251         }
 252         return 1;
 253 }
 254 
 255 static int sqlite_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
 256 {
 257         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 258         char *errmsg = NULL;
 259 
 260         if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
 261                 pdo_sqlite_error(dbh);
 262                 if (errmsg)
 263                         sqlite3_free(errmsg);
 264                 return 0;
 265         }
 266         return 1;
 267 }
 268 
 269 static int sqlite_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
 270 {
 271         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 272         char *errmsg = NULL;
 273 
 274         if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
 275                 pdo_sqlite_error(dbh);
 276                 if (errmsg)
 277                         sqlite3_free(errmsg);
 278                 return 0;
 279         }
 280         return 1;
 281 }
 282 
 283 static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
 284 {
 285         switch (attr) {
 286                 case PDO_ATTR_CLIENT_VERSION:
 287                 case PDO_ATTR_SERVER_VERSION:
 288                         ZVAL_STRING(return_value, (char *)sqlite3_libversion(), 1);
 289                         break;
 290                 
 291                 default:
 292                         return 0;       
 293         }
 294 
 295         return 1;
 296 }
 297 
 298 static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
 299 {
 300         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 301 
 302         switch (attr) {
 303                 case PDO_ATTR_TIMEOUT:
 304                         convert_to_long(val);
 305                         sqlite3_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
 306                         return 1;
 307         }
 308         return 0;
 309 }
 310 
 311 static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
 312                 int argc, sqlite3_value **argv, sqlite3_context *context,
 313                 int is_agg TSRMLS_DC)
 314 {
 315         zval ***zargs = NULL;
 316         zval *retval = NULL;
 317         int i;
 318         int ret;
 319         int fake_argc;
 320         zval **agg_context = NULL;
 321         
 322         if (is_agg) {
 323                 is_agg = 2;
 324         }
 325         
 326         fake_argc = argc + is_agg;
 327         
 328         fc->fci.size = sizeof(fc->fci);
 329         fc->fci.function_table = EG(function_table);
 330         fc->fci.function_name = cb;
 331         fc->fci.symbol_table = NULL;
 332         fc->fci.object_ptr = NULL;
 333         fc->fci.retval_ptr_ptr = &retval;
 334         fc->fci.param_count = fake_argc;
 335         
 336         /* build up the params */
 337 
 338         if (fake_argc) {
 339                 zargs = (zval ***)safe_emalloc(fake_argc, sizeof(zval **), 0);
 340         }
 341 
 342         if (is_agg) {
 343                 /* summon the aggregation context */
 344                 agg_context = (zval**)sqlite3_aggregate_context(context, sizeof(zval*));
 345                 if (!*agg_context) {
 346                         MAKE_STD_ZVAL(*agg_context);
 347                         ZVAL_NULL(*agg_context);
 348                 }
 349                 zargs[0] = agg_context;
 350 
 351                 zargs[1] = emalloc(sizeof(zval*));
 352                 MAKE_STD_ZVAL(*zargs[1]);
 353                 ZVAL_LONG(*zargs[1], sqlite3_aggregate_count(context));
 354         }
 355         
 356         for (i = 0; i < argc; i++) {
 357                 zargs[i + is_agg] = emalloc(sizeof(zval *));
 358                 MAKE_STD_ZVAL(*zargs[i + is_agg]);
 359 
 360                 /* get the value */
 361                 switch (sqlite3_value_type(argv[i])) {
 362                         case SQLITE_INTEGER:
 363                                 ZVAL_LONG(*zargs[i + is_agg], sqlite3_value_int(argv[i]));
 364                                 break;
 365 
 366                         case SQLITE_FLOAT:
 367                                 ZVAL_DOUBLE(*zargs[i + is_agg], sqlite3_value_double(argv[i]));
 368                                 break;
 369 
 370                         case SQLITE_NULL:
 371                                 ZVAL_NULL(*zargs[i + is_agg]);
 372                                 break;
 373 
 374                         case SQLITE_BLOB:
 375                         case SQLITE3_TEXT:
 376                         default:
 377                                 ZVAL_STRINGL(*zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]),
 378                                                 sqlite3_value_bytes(argv[i]), 1);
 379                                 break;
 380                 }
 381         }
 382 
 383 
 384         fc->fci.params = zargs;
 385 
 386 
 387         if ((ret = zend_call_function(&fc->fci, &fc->fcc TSRMLS_CC)) == FAILURE) {
 388                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
 389         }
 390 
 391         /* clean up the params */
 392         if (zargs) {
 393                 for (i = is_agg; i < fake_argc; i++) {
 394                         zval_ptr_dtor(zargs[i]);
 395                         efree(zargs[i]);
 396                 }
 397                 if (is_agg) {
 398                         zval_ptr_dtor(zargs[1]);
 399                         efree(zargs[1]);
 400                 }
 401                 efree(zargs);
 402         }
 403 
 404         if (!is_agg || !argv) {
 405                 /* only set the sqlite return value if we are a scalar function,
 406                  * or if we are finalizing an aggregate */
 407                 if (retval) {
 408                         switch (Z_TYPE_P(retval)) {
 409                                 case IS_LONG:
 410                                         sqlite3_result_int(context, Z_LVAL_P(retval));
 411                                         break;
 412 
 413                                 case IS_NULL:
 414                                         sqlite3_result_null(context);
 415                                         break;
 416 
 417                                 case IS_DOUBLE:
 418                                         sqlite3_result_double(context, Z_DVAL_P(retval));
 419                                         break;
 420 
 421                                 default:
 422                                         convert_to_string_ex(&retval);
 423                                         sqlite3_result_text(context, Z_STRVAL_P(retval),
 424                                                 Z_STRLEN_P(retval), SQLITE_TRANSIENT);
 425                                         break;
 426                         }
 427                 } else {
 428                         sqlite3_result_error(context, "failed to invoke callback", 0);
 429                 }
 430 
 431                 if (agg_context) {
 432                         zval_ptr_dtor(agg_context);
 433                 }
 434         } else {
 435                 /* we're stepping in an aggregate; the return value goes into
 436                  * the context */
 437                 if (agg_context) {
 438                         zval_ptr_dtor(agg_context);
 439                 }
 440                 if (retval) {
 441                         *agg_context = retval;
 442                         retval = NULL;
 443                 } else {
 444                         *agg_context = NULL;
 445                 }
 446         }
 447 
 448         if (retval) {
 449                 zval_ptr_dtor(&retval);
 450         }
 451 
 452         return ret;
 453 }
 454 
 455 static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
 456         sqlite3_value **argv)
 457 {
 458         struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
 459         TSRMLS_FETCH();
 460 
 461         do_callback(&func->afunc, func->func, argc, argv, context, 0 TSRMLS_CC);
 462 }
 463 
 464 static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
 465         sqlite3_value **argv)
 466 {
 467         struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
 468         TSRMLS_FETCH();
 469 
 470         do_callback(&func->astep, func->step, argc, argv, context, 1 TSRMLS_CC);
 471 }
 472 
 473 static void php_sqlite3_func_final_callback(sqlite3_context *context)
 474 {
 475         struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
 476         TSRMLS_FETCH();
 477 
 478         do_callback(&func->afini, func->fini, 0, NULL, context, 1 TSRMLS_CC);
 479 }
 480 
 481 static int php_sqlite3_collation_callback(void *context,
 482         int string1_len, const void *string1,
 483         int string2_len, const void *string2)
 484 {
 485         int ret;
 486         zval *zstring1, *zstring2;
 487         zval **zargs[2];
 488         zval *retval = NULL;
 489         struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
 490         TSRMLS_FETCH();
 491 
 492         collation->fc.fci.size = sizeof(collation->fc.fci);
 493         collation->fc.fci.function_table = EG(function_table);
 494         collation->fc.fci.function_name = collation->callback;
 495         collation->fc.fci.symbol_table = NULL;
 496         collation->fc.fci.object_ptr = NULL;
 497         collation->fc.fci.retval_ptr_ptr = &retval;
 498 
 499         // Prepare the arguments.
 500         MAKE_STD_ZVAL(zstring1);
 501         ZVAL_STRINGL(zstring1, (char *) string1, string1_len, 1);
 502         zargs[0] = &zstring1;
 503         MAKE_STD_ZVAL(zstring2);
 504         ZVAL_STRINGL(zstring2, (char *) string2, string2_len, 1);
 505         zargs[1] = &zstring2;
 506         collation->fc.fci.param_count = 2;
 507         collation->fc.fci.params = zargs;
 508 
 509         if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc TSRMLS_CC)) == FAILURE) {
 510                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
 511         }
 512         else if (retval) {
 513                 if (Z_TYPE_P(retval) != IS_LONG) {
 514                         convert_to_long_ex(&retval);
 515                 }
 516                 ret = 0;
 517                 if (Z_LVAL_P(retval) > 0) {
 518                         ret = 1;
 519                 }
 520                 else if (Z_LVAL_P(retval) < 0) {
 521                         ret = -1;
 522                 }
 523                 zval_ptr_dtor(&retval);
 524         }
 525 
 526         zval_ptr_dtor(zargs[0]);
 527         zval_ptr_dtor(zargs[1]);
 528 
 529         return ret;
 530 }
 531 
 532 /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount])
 533    Registers a UDF with the sqlite db handle */
 534 static PHP_METHOD(SQLite, sqliteCreateFunction)
 535 {
 536         struct pdo_sqlite_func *func;
 537         zval *callback;
 538         char *func_name;
 539         int func_name_len;
 540         long argc = -1;
 541         char *cbname = NULL;
 542         pdo_dbh_t *dbh;
 543         pdo_sqlite_db_handle *H;
 544         int ret;
 545 
 546         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l",
 547                         &func_name, &func_name_len, &callback, &argc)) {
 548                 RETURN_FALSE;
 549         }
 550         
 551         dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
 552         PDO_CONSTRUCT_CHECK;
 553 
 554         if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
 555                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
 556                 efree(cbname);
 557                 RETURN_FALSE;
 558         }
 559         efree(cbname);
 560         
 561         H = (pdo_sqlite_db_handle *)dbh->driver_data;
 562 
 563         func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
 564 
 565         ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
 566                         func, php_sqlite3_func_callback, NULL, NULL);
 567         if (ret == SQLITE_OK) {
 568                 func->funcname = estrdup(func_name);
 569                 
 570                 MAKE_STD_ZVAL(func->func);
 571                 MAKE_COPY_ZVAL(&callback, func->func);
 572                 
 573                 func->argc = argc;
 574 
 575                 func->next = H->funcs;
 576                 H->funcs = func;
 577 
 578                 RETURN_TRUE;
 579         }
 580 
 581         efree(func);
 582         RETURN_FALSE;
 583 }
 584 /* }}} */
 585 
 586 /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
 587    Registers a UDF with the sqlite db handle */
 588 
 589 /* The step function should have the prototype:
 590    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
 591 
 592    $context will be null for the first row; on subsequent rows it will have
 593    the value that was previously returned from the step function; you should
 594    use this to maintain state for the aggregate.
 595 
 596    The fini function should have the prototype:
 597    mixed fini(mixed $context, int $rownumber)
 598 
 599    $context will hold the return value from the very last call to the step function.
 600    rownumber will hold the number of rows over which the aggregate was performed.
 601    The return value of this function will be used as the return value for this
 602    aggregate UDF.
 603 */
 604    
 605 static PHP_METHOD(SQLite, sqliteCreateAggregate)
 606 {
 607         struct pdo_sqlite_func *func;
 608         zval *step_callback, *fini_callback;
 609         char *func_name;
 610         int func_name_len;
 611         long argc = -1;
 612         char *cbname = NULL;
 613         pdo_dbh_t *dbh;
 614         pdo_sqlite_db_handle *H;
 615         int ret;
 616 
 617         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l",
 618                         &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
 619                 RETURN_FALSE;
 620         }
 621         
 622         dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
 623         PDO_CONSTRUCT_CHECK;
 624 
 625         if (!zend_is_callable(step_callback, 0, &cbname TSRMLS_CC)) {
 626                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
 627                 efree(cbname);
 628                 RETURN_FALSE;
 629         }
 630         efree(cbname);
 631         if (!zend_is_callable(fini_callback, 0, &cbname TSRMLS_CC)) {
 632                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
 633                 efree(cbname);
 634                 RETURN_FALSE;
 635         }
 636         efree(cbname);
 637         
 638         H = (pdo_sqlite_db_handle *)dbh->driver_data;
 639 
 640         func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
 641 
 642         ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
 643                         func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
 644         if (ret == SQLITE_OK) {
 645                 func->funcname = estrdup(func_name);
 646                 
 647                 MAKE_STD_ZVAL(func->step);
 648                 MAKE_COPY_ZVAL(&step_callback, func->step);
 649 
 650                 MAKE_STD_ZVAL(func->fini);
 651                 MAKE_COPY_ZVAL(&fini_callback, func->fini);
 652                 
 653                 func->argc = argc;
 654 
 655                 func->next = H->funcs;
 656                 H->funcs = func;
 657 
 658                 RETURN_TRUE;
 659         }
 660 
 661         efree(func);
 662         RETURN_FALSE;
 663 }
 664 /* }}} */
 665 
 666 /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
 667    Registers a collation with the sqlite db handle */
 668 static PHP_METHOD(SQLite, sqliteCreateCollation)
 669 {
 670         struct pdo_sqlite_collation *collation;
 671         zval *callback;
 672         char *collation_name;
 673         int collation_name_len;
 674         char *cbname = NULL;
 675         pdo_dbh_t *dbh;
 676         pdo_sqlite_db_handle *H;
 677         int ret;
 678 
 679         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz",
 680                 &collation_name, &collation_name_len, &callback)) {
 681                 RETURN_FALSE;
 682         }
 683 
 684         dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
 685         PDO_CONSTRUCT_CHECK;
 686 
 687         if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
 688                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
 689                 efree(cbname);
 690                 RETURN_FALSE;
 691         }
 692         efree(cbname);
 693 
 694         H = (pdo_sqlite_db_handle *)dbh->driver_data;
 695 
 696         collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
 697 
 698         ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
 699         if (ret == SQLITE_OK) {
 700                 collation->name = estrdup(collation_name);
 701 
 702                 MAKE_STD_ZVAL(collation->callback);
 703                 MAKE_COPY_ZVAL(&callback, collation->callback);
 704 
 705                 collation->next = H->collations;
 706                 H->collations = collation;
 707 
 708                 RETURN_TRUE;
 709         }
 710 
 711         efree(collation);
 712         RETURN_FALSE;
 713 }
 714 /* }}} */
 715 
 716 static const zend_function_entry dbh_methods[] = {
 717         PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
 718         PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
 719         PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
 720         PHP_FE_END
 721 };
 722 
 723 static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
 724 {
 725         switch (kind) {
 726                 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
 727                         return dbh_methods;
 728 
 729                 default:
 730                         return NULL;
 731         }
 732 }
 733 
 734 static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh TSRMLS_DC)
 735 {
 736         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
 737         /* unregister functions, so that they don't linger for the next
 738          * request */
 739         if (H) {
 740                 pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
 741         }
 742 }
 743 
 744 static struct pdo_dbh_methods sqlite_methods = {
 745         sqlite_handle_closer,
 746         sqlite_handle_preparer,
 747         sqlite_handle_doer,
 748         sqlite_handle_quoter,
 749         sqlite_handle_begin,
 750         sqlite_handle_commit,
 751         sqlite_handle_rollback,
 752         pdo_sqlite_set_attr,
 753         pdo_sqlite_last_insert_id,
 754         pdo_sqlite_fetch_error_func,
 755         pdo_sqlite_get_attribute,
 756         NULL,   /* check_liveness: not needed */
 757         get_driver_methods,
 758         pdo_sqlite_request_shutdown
 759 };
 760 
 761 static char *make_filename_safe(const char *filename TSRMLS_DC)
 762 {
 763         if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
 764                 char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
 765 
 766                 if (!fullpath) {
 767                         return NULL;
 768                 }
 769 
 770                 if (php_check_open_basedir(fullpath TSRMLS_CC)) {
 771                         efree(fullpath);
 772                         return NULL;
 773                 }
 774                 return fullpath;
 775         }
 776         return estrdup(filename);
 777 }
 778 
 779 static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
 780                 const char *arg5, const char *arg6)
 781 {
 782         char *filename;
 783         switch (access_type) {
 784                 case SQLITE_COPY: {
 785                         TSRMLS_FETCH();
 786                         filename = make_filename_safe(arg4 TSRMLS_CC);
 787                         if (!filename) {
 788                                 return SQLITE_DENY;
 789                         }
 790                         efree(filename);
 791                         return SQLITE_OK;
 792                 }
 793 
 794                 case SQLITE_ATTACH: {
 795                         TSRMLS_FETCH();
 796                         filename = make_filename_safe(arg3 TSRMLS_CC);
 797                         if (!filename) {
 798                                 return SQLITE_DENY;
 799                         }
 800                         efree(filename);
 801                         return SQLITE_OK;
 802                 }
 803 
 804                 default:
 805                         /* access allowed */
 806                         return SQLITE_OK;
 807         }
 808 }
 809 
 810 static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
 811 {
 812         pdo_sqlite_db_handle *H;
 813         int i, ret = 0;
 814         long timeout = 60;
 815         char *filename;
 816 
 817         H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
 818         
 819         H->einfo.errcode = 0;
 820         H->einfo.errmsg = NULL;
 821         dbh->driver_data = H;
 822 
 823         filename = make_filename_safe(dbh->data_source TSRMLS_CC);
 824 
 825         if (!filename) {
 826                 zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
 827                         "open_basedir prohibits opening %s",
 828                         dbh->data_source);
 829                 goto cleanup;
 830         }
 831 
 832         i = sqlite3_open(filename, &H->db);
 833         efree(filename);
 834 
 835         if (i != SQLITE_OK) {
 836                 pdo_sqlite_error(dbh);
 837                 goto cleanup;
 838         }
 839 
 840         if (PG(open_basedir) && *PG(open_basedir)) {
 841                 sqlite3_set_authorizer(H->db, authorizer, NULL);
 842         }
 843 
 844         if (driver_options) {
 845                 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
 846         }
 847         sqlite3_busy_timeout(H->db, timeout * 1000);
 848 
 849         dbh->alloc_own_columns = 1;
 850         dbh->max_escaped_char_length = 2;
 851 
 852         ret = 1;
 853         
 854 cleanup:
 855         dbh->methods = &sqlite_methods;
 856         
 857         return ret;
 858 }
 859 /* }}} */
 860 
 861 pdo_driver_t pdo_sqlite_driver = {
 862         PDO_DRIVER_HEADER(sqlite),
 863         pdo_sqlite_handle_factory
 864 };
 865 
 866 /*
 867  * Local variables:
 868  * tab-width: 4
 869  * c-basic-offset: 4
 870  * End:
 871  * vim600: noet sw=4 ts=4 fdm=marker
 872  * vim<600: noet sw=4 ts=4
 873  */

/* [<][>][^][v][top][bottom][index][help] */