PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/pdo_sqlite - sqlite_driver.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 307 386 79.5 %
Date: 2015-01-26 Functions: 25 26 96.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Mon, 26 Jan 2015 14:46:50 +0000 (28 hours ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.