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: 322 400 80.5 %
Date: 2014-11-25 Functions: 25 26 96.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 5                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2014 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         346 : int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
      35             : {
      36         346 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
      37         346 :         pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
      38         346 :         pdo_sqlite_error_info *einfo = &H->einfo;
      39             : 
      40         346 :         einfo->errcode = sqlite3_errcode(H->db);
      41         346 :         einfo->file = file;
      42         346 :         einfo->line = line;
      43             : 
      44         346 :         if (einfo->errcode != SQLITE_OK) {
      45         346 :                 if (einfo->errmsg) {
      46         231 :                         pefree(einfo->errmsg, dbh->is_persistent);
      47             :                 }
      48         346 :                 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         346 :         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         346 :                         strncpy(*pdo_err, "HY000", sizeof("HY000"));
      77             :                         break;
      78             :         }
      79             : 
      80         346 :         if (!dbh->methods) {
      81           1 :                 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         346 :         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 TSRMLS_DC)
      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, 1);
      97             :         }
      98             : 
      99           9 :         return 1;
     100             : }
     101             : 
     102         174 : static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC)
     103             : {
     104             :         struct pdo_sqlite_func *func;
     105             : 
     106         352 :         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           4 :                 if (func->func) {
     122           3 :                         zval_ptr_dtor(&func->func);
     123             :                 }
     124           4 :                 if (func->step) {
     125           1 :                         zval_ptr_dtor(&func->step);
     126             :                 }
     127           4 :                 if (func->fini) {
     128           1 :                         zval_ptr_dtor(&func->fini);
     129             :                 }
     130           4 :                 efree(func);
     131             :         }
     132             : 
     133         349 :         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           1 :                 if (collation->callback) {
     149           1 :                         zval_ptr_dtor(&collation->callback);
     150             :                 }
     151           1 :                 efree(collation);
     152             :         }
     153         174 : }
     154             : 
     155         169 : static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
     156             : {
     157         169 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     158             :         
     159         169 :         if (H) {
     160         169 :                 pdo_sqlite_error_info *einfo = &H->einfo;
     161             : 
     162         169 :                 pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
     163         169 :                 if (H->db) {
     164         169 :                         sqlite3_close(H->db);
     165         169 :                         H->db = NULL;
     166             :                 }
     167         169 :                 if (einfo->errmsg) {
     168         114 :                         pefree(einfo->errmsg, dbh->is_persistent);
     169         114 :                         einfo->errmsg = NULL;
     170             :                 }
     171         169 :                 pefree(H, dbh->is_persistent);
     172         169 :                 dbh->driver_data = NULL;
     173             :         }
     174         169 :         return 0;
     175             : }
     176             : /* }}} */
     177             : 
     178         174 : 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         174 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     181         174 :         pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
     182             :         int i;
     183             :         const char *tail;
     184             : 
     185         174 :         S->H = H;
     186         174 :         stmt->driver_data = S;
     187         174 :         stmt->methods = &sqlite_stmt_methods;
     188         174 :         stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
     189             : 
     190         174 :         if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
     191           0 :                 H->einfo.errcode = SQLITE_ERROR;
     192           0 :                 pdo_sqlite_error(dbh);
     193           0 :                 return 0;
     194             :         }
     195             : 
     196         174 :         i = sqlite3_prepare(H->db, sql, sql_len, &S->stmt, &tail);
     197         174 :         if (i == SQLITE_OK) {
     198         173 :                 return 1;
     199             :         }
     200             : 
     201           1 :         pdo_sqlite_error(dbh);
     202             : 
     203           1 :         return 0;
     204             : }
     205             : 
     206         512 : static long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
     207             : {
     208         512 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     209         512 :         char *errmsg = NULL;
     210             : 
     211         512 :         if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
     212         342 :                 pdo_sqlite_error(dbh);
     213         342 :                 if (errmsg)
     214         342 :                         sqlite3_free(errmsg);
     215             : 
     216         342 :                 return -1;
     217             :         } else {
     218         170 :                 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 TSRMLS_DC)
     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) TSRMLS_CC);
     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  TSRMLS_DC)
     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 TSRMLS_DC)
     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 TSRMLS_DC)
     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 TSRMLS_DC)
     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, long attr, zval *return_value TSRMLS_DC)
     284             : {
     285           2 :         switch (attr) {
     286             :                 case PDO_ATTR_CLIENT_VERSION:
     287             :                 case PDO_ATTR_SERVER_VERSION:
     288           2 :                         ZVAL_STRING(return_value, (char *)sqlite3_libversion(), 1);
     289           2 :                         break;
     290             :                 
     291             :                 default:
     292           0 :                         return 0;       
     293             :         }
     294             : 
     295           2 :         return 1;
     296             : }
     297             : 
     298          28 : static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
     299             : {
     300          28 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     301             : 
     302          28 :         switch (attr) {
     303             :                 case PDO_ATTR_TIMEOUT:
     304          21 :                         convert_to_long(val);
     305          21 :                         sqlite3_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
     306          21 :                         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 TSRMLS_DC)
     314             : {
     315           5 :         zval ***zargs = NULL;
     316           5 :         zval *retval = NULL;
     317             :         int i;
     318             :         int ret;
     319             :         int fake_argc;
     320           5 :         zval **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 :         fc->fci.function_name = cb;
     331           5 :         fc->fci.symbol_table = NULL;
     332           5 :         fc->fci.object_ptr = NULL;
     333           5 :         fc->fci.retval_ptr_ptr = &retval;
     334           5 :         fc->fci.param_count = fake_argc;
     335             :         
     336             :         /* build up the params */
     337             : 
     338           5 :         if (fake_argc) {
     339           5 :                 zargs = (zval ***)safe_emalloc(fake_argc, sizeof(zval **), 0);
     340             :         }
     341             : 
     342           5 :         if (is_agg) {
     343             :                 /* summon the aggregation context */
     344           3 :                 agg_context = (zval**)sqlite3_aggregate_context(context, sizeof(zval*));
     345           3 :                 if (!*agg_context) {
     346           1 :                         MAKE_STD_ZVAL(*agg_context);
     347           1 :                         ZVAL_NULL(*agg_context);
     348             :                 }
     349           3 :                 zargs[0] = agg_context;
     350             : 
     351           3 :                 zargs[1] = emalloc(sizeof(zval*));
     352           3 :                 MAKE_STD_ZVAL(*zargs[1]);
     353           3 :                 ZVAL_LONG(*zargs[1], sqlite3_aggregate_count(context));
     354             :         }
     355             :         
     356           9 :         for (i = 0; i < argc; i++) {
     357           4 :                 zargs[i + is_agg] = emalloc(sizeof(zval *));
     358           4 :                 MAKE_STD_ZVAL(*zargs[i + is_agg]);
     359             : 
     360             :                 /* get the value */
     361           4 :                 switch (sqlite3_value_type(argv[i])) {
     362             :                         case SQLITE_INTEGER:
     363           0 :                                 ZVAL_LONG(*zargs[i + is_agg], sqlite3_value_int(argv[i]));
     364           0 :                                 break;
     365             : 
     366             :                         case SQLITE_FLOAT:
     367           0 :                                 ZVAL_DOUBLE(*zargs[i + is_agg], sqlite3_value_double(argv[i]));
     368           0 :                                 break;
     369             : 
     370             :                         case SQLITE_NULL:
     371           0 :                                 ZVAL_NULL(*zargs[i + is_agg]);
     372           0 :                                 break;
     373             : 
     374             :                         case SQLITE_BLOB:
     375             :                         case SQLITE3_TEXT:
     376             :                         default:
     377           4 :                                 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           5 :         fc->fci.params = zargs;
     385             : 
     386             : 
     387           5 :         if ((ret = zend_call_function(&fc->fci, &fc->fcc TSRMLS_CC)) == FAILURE) {
     388           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
     389             :         }
     390             : 
     391             :         /* clean up the params */
     392           5 :         if (zargs) {
     393           9 :                 for (i = is_agg; i < fake_argc; i++) {
     394           4 :                         zval_ptr_dtor(zargs[i]);
     395           4 :                         efree(zargs[i]);
     396             :                 }
     397           5 :                 if (is_agg) {
     398           3 :                         zval_ptr_dtor(zargs[1]);
     399           3 :                         efree(zargs[1]);
     400             :                 }
     401           5 :                 efree(zargs);
     402             :         }
     403             : 
     404           8 :         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           3 :                 if (retval) {
     408           3 :                         switch (Z_TYPE_P(retval)) {
     409             :                                 case IS_LONG:
     410           0 :                                         sqlite3_result_int(context, Z_LVAL_P(retval));
     411           0 :                                         break;
     412             : 
     413             :                                 case IS_NULL:
     414           0 :                                         sqlite3_result_null(context);
     415           0 :                                         break;
     416             : 
     417             :                                 case IS_DOUBLE:
     418           0 :                                         sqlite3_result_double(context, Z_DVAL_P(retval));
     419           0 :                                         break;
     420             : 
     421             :                                 default:
     422           3 :                                         convert_to_string_ex(&retval);
     423           3 :                                         sqlite3_result_text(context, Z_STRVAL_P(retval),
     424           3 :                                                 Z_STRLEN_P(retval), SQLITE_TRANSIENT);
     425             :                                         break;
     426             :                         }
     427             :                 } else {
     428           0 :                         sqlite3_result_error(context, "failed to invoke callback", 0);
     429             :                 }
     430             : 
     431           3 :                 if (agg_context) {
     432           1 :                         zval_ptr_dtor(agg_context);
     433             :                 }
     434             :         } else {
     435             :                 /* we're stepping in an aggregate; the return value goes into
     436             :                  * the context */
     437           2 :                 if (agg_context) {
     438           2 :                         zval_ptr_dtor(agg_context);
     439             :                 }
     440           2 :                 if (retval) {
     441           2 :                         *agg_context = retval;
     442           2 :                         retval = NULL;
     443             :                 } else {
     444           0 :                         *agg_context = NULL;
     445             :                 }
     446             :         }
     447             : 
     448           5 :         if (retval) {
     449           3 :                 zval_ptr_dtor(&retval);
     450             :         }
     451             : 
     452           5 :         return ret;
     453             : }
     454             : 
     455           2 : static void php_sqlite3_func_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             :         TSRMLS_FETCH();
     460             : 
     461           2 :         do_callback(&func->afunc, func->func, argc, argv, context, 0 TSRMLS_CC);
     462           2 : }
     463             : 
     464           2 : static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
     465             :         sqlite3_value **argv)
     466             : {
     467           2 :         struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
     468             :         TSRMLS_FETCH();
     469             : 
     470           2 :         do_callback(&func->astep, func->step, argc, argv, context, 1 TSRMLS_CC);
     471           2 : }
     472             : 
     473           1 : static void php_sqlite3_func_final_callback(sqlite3_context *context)
     474             : {
     475           1 :         struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
     476             :         TSRMLS_FETCH();
     477             : 
     478           1 :         do_callback(&func->afini, func->fini, 0, NULL, context, 1 TSRMLS_CC);
     479           1 : }
     480             : 
     481           3 : 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           3 :         zval *retval = NULL;
     489           3 :         struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
     490             :         TSRMLS_FETCH();
     491             : 
     492           3 :         collation->fc.fci.size = sizeof(collation->fc.fci);
     493           3 :         collation->fc.fci.function_table = EG(function_table);
     494           3 :         collation->fc.fci.function_name = collation->callback;
     495           3 :         collation->fc.fci.symbol_table = NULL;
     496           3 :         collation->fc.fci.object_ptr = NULL;
     497           3 :         collation->fc.fci.retval_ptr_ptr = &retval;
     498             : 
     499             :         // Prepare the arguments.
     500           3 :         MAKE_STD_ZVAL(zstring1);
     501           3 :         ZVAL_STRINGL(zstring1, (char *) string1, string1_len, 1);
     502           3 :         zargs[0] = &zstring1;
     503           3 :         MAKE_STD_ZVAL(zstring2);
     504           3 :         ZVAL_STRINGL(zstring2, (char *) string2, string2_len, 1);
     505           3 :         zargs[1] = &zstring2;
     506           3 :         collation->fc.fci.param_count = 2;
     507           3 :         collation->fc.fci.params = zargs;
     508             : 
     509           3 :         if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc TSRMLS_CC)) == FAILURE) {
     510           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
     511             :         }
     512           3 :         else if (retval) {
     513           3 :                 if (Z_TYPE_P(retval) != IS_LONG) {
     514           0 :                         convert_to_long_ex(&retval);
     515             :                 }
     516           3 :                 ret = 0;
     517           3 :                 if (Z_LVAL_P(retval) > 0) {
     518           0 :                         ret = 1;
     519             :                 }
     520           3 :                 else if (Z_LVAL_P(retval) < 0) {
     521           3 :                         ret = -1;
     522             :                 }
     523           3 :                 zval_ptr_dtor(&retval);
     524             :         }
     525             : 
     526           3 :         zval_ptr_dtor(zargs[0]);
     527           3 :         zval_ptr_dtor(zargs[1]);
     528             : 
     529           3 :         return ret;
     530             : }
     531             : 
     532             : /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount])
     533             :    Registers a UDF with the sqlite db handle */
     534           4 : 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           4 :         long argc = -1;
     541           4 :         char *cbname = NULL;
     542             :         pdo_dbh_t *dbh;
     543             :         pdo_sqlite_db_handle *H;
     544             :         int ret;
     545             : 
     546           4 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l",
     547             :                         &func_name, &func_name_len, &callback, &argc)) {
     548           0 :                 RETURN_FALSE;
     549             :         }
     550             :         
     551           4 :         dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
     552           4 :         PDO_CONSTRUCT_CHECK;
     553             : 
     554           4 :         if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
     555           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
     556           1 :                 efree(cbname);
     557           1 :                 RETURN_FALSE;
     558             :         }
     559           3 :         efree(cbname);
     560             :         
     561           3 :         H = (pdo_sqlite_db_handle *)dbh->driver_data;
     562             : 
     563           3 :         func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
     564             : 
     565           3 :         ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
     566             :                         func, php_sqlite3_func_callback, NULL, NULL);
     567           3 :         if (ret == SQLITE_OK) {
     568           3 :                 func->funcname = estrdup(func_name);
     569             :                 
     570           3 :                 MAKE_STD_ZVAL(func->func);
     571           9 :                 MAKE_COPY_ZVAL(&callback, func->func);
     572             :                 
     573           3 :                 func->argc = argc;
     574             : 
     575           3 :                 func->next = H->funcs;
     576           3 :                 H->funcs = func;
     577             : 
     578           3 :                 RETURN_TRUE;
     579             :         }
     580             : 
     581           0 :         efree(func);
     582           0 :         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           3 : 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           3 :         long argc = -1;
     612           3 :         char *cbname = NULL;
     613             :         pdo_dbh_t *dbh;
     614             :         pdo_sqlite_db_handle *H;
     615             :         int ret;
     616             : 
     617           3 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l",
     618             :                         &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
     619           0 :                 RETURN_FALSE;
     620             :         }
     621             :         
     622           3 :         dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
     623           3 :         PDO_CONSTRUCT_CHECK;
     624             : 
     625           3 :         if (!zend_is_callable(step_callback, 0, &cbname TSRMLS_CC)) {
     626           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
     627           1 :                 efree(cbname);
     628           1 :                 RETURN_FALSE;
     629             :         }
     630           2 :         efree(cbname);
     631           2 :         if (!zend_is_callable(fini_callback, 0, &cbname TSRMLS_CC)) {
     632           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
     633           1 :                 efree(cbname);
     634           1 :                 RETURN_FALSE;
     635             :         }
     636           1 :         efree(cbname);
     637             :         
     638           1 :         H = (pdo_sqlite_db_handle *)dbh->driver_data;
     639             : 
     640           1 :         func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
     641             : 
     642           1 :         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           1 :         if (ret == SQLITE_OK) {
     645           1 :                 func->funcname = estrdup(func_name);
     646             :                 
     647           1 :                 MAKE_STD_ZVAL(func->step);
     648           3 :                 MAKE_COPY_ZVAL(&step_callback, func->step);
     649             : 
     650           1 :                 MAKE_STD_ZVAL(func->fini);
     651           3 :                 MAKE_COPY_ZVAL(&fini_callback, func->fini);
     652             :                 
     653           1 :                 func->argc = argc;
     654             : 
     655           1 :                 func->next = H->funcs;
     656           1 :                 H->funcs = func;
     657             : 
     658           1 :                 RETURN_TRUE;
     659             :         }
     660             : 
     661           0 :         efree(func);
     662           0 :         RETURN_FALSE;
     663             : }
     664             : /* }}} */
     665             : 
     666             : /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
     667             :    Registers a collation with the sqlite db handle */
     668           1 : 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           1 :         char *cbname = NULL;
     675             :         pdo_dbh_t *dbh;
     676             :         pdo_sqlite_db_handle *H;
     677             :         int ret;
     678             : 
     679           1 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz",
     680             :                 &collation_name, &collation_name_len, &callback)) {
     681           0 :                 RETURN_FALSE;
     682             :         }
     683             : 
     684           1 :         dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
     685           1 :         PDO_CONSTRUCT_CHECK;
     686             : 
     687           1 :         if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
     688           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
     689           0 :                 efree(cbname);
     690           0 :                 RETURN_FALSE;
     691             :         }
     692           1 :         efree(cbname);
     693             : 
     694           1 :         H = (pdo_sqlite_db_handle *)dbh->driver_data;
     695             : 
     696           1 :         collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
     697             : 
     698           1 :         ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
     699           1 :         if (ret == SQLITE_OK) {
     700           1 :                 collation->name = estrdup(collation_name);
     701             : 
     702           1 :                 MAKE_STD_ZVAL(collation->callback);
     703           3 :                 MAKE_COPY_ZVAL(&callback, collation->callback);
     704             : 
     705           1 :                 collation->next = H->collations;
     706           1 :                 H->collations = collation;
     707             : 
     708           1 :                 RETURN_TRUE;
     709             :         }
     710             : 
     711           0 :         efree(collation);
     712           0 :         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           7 : static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
     724             : {
     725           7 :         switch (kind) {
     726             :                 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
     727           7 :                         return dbh_methods;
     728             : 
     729             :                 default:
     730           0 :                         return NULL;
     731             :         }
     732             : }
     733             : 
     734           5 : static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh TSRMLS_DC)
     735             : {
     736           5 :         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           5 :         if (H) {
     740           5 :                 pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
     741             :         }
     742           5 : }
     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         170 : static char *make_filename_safe(const char *filename TSRMLS_DC)
     762             : {
     763         170 :         if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
     764          16 :                 char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
     765             : 
     766          16 :                 if (!fullpath) {
     767           0 :                         return NULL;
     768             :                 }
     769             : 
     770          16 :                 if (php_check_open_basedir(fullpath TSRMLS_CC)) {
     771           0 :                         efree(fullpath);
     772           0 :                         return NULL;
     773             :                 }
     774          16 :                 return fullpath;
     775             :         }
     776         154 :         return estrdup(filename);
     777             : }
     778             : 
     779           0 : 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           0 :         switch (access_type) {
     784             :                 case SQLITE_COPY: {
     785             :                         TSRMLS_FETCH();
     786           0 :                         filename = make_filename_safe(arg4 TSRMLS_CC);
     787           0 :                         if (!filename) {
     788           0 :                                 return SQLITE_DENY;
     789             :                         }
     790           0 :                         efree(filename);
     791           0 :                         return SQLITE_OK;
     792             :                 }
     793             : 
     794             :                 case SQLITE_ATTACH: {
     795             :                         TSRMLS_FETCH();
     796           0 :                         filename = make_filename_safe(arg3 TSRMLS_CC);
     797           0 :                         if (!filename) {
     798           0 :                                 return SQLITE_DENY;
     799             :                         }
     800           0 :                         efree(filename);
     801           0 :                         return SQLITE_OK;
     802             :                 }
     803             : 
     804             :                 default:
     805             :                         /* access allowed */
     806           0 :                         return SQLITE_OK;
     807             :         }
     808             : }
     809             : 
     810         170 : static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
     811             : {
     812             :         pdo_sqlite_db_handle *H;
     813         170 :         int i, ret = 0;
     814         170 :         long timeout = 60;
     815             :         char *filename;
     816             : 
     817         170 :         H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
     818             :         
     819         170 :         H->einfo.errcode = 0;
     820         170 :         H->einfo.errmsg = NULL;
     821         170 :         dbh->driver_data = H;
     822             : 
     823         170 :         filename = make_filename_safe(dbh->data_source TSRMLS_CC);
     824             : 
     825         170 :         if (!filename) {
     826           0 :                 zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
     827             :                         "open_basedir prohibits opening %s",
     828             :                         dbh->data_source);
     829           0 :                 goto cleanup;
     830             :         }
     831             : 
     832         170 :         i = sqlite3_open(filename, &H->db);
     833         170 :         efree(filename);
     834             : 
     835         170 :         if (i != SQLITE_OK) {
     836           1 :                 pdo_sqlite_error(dbh);
     837           1 :                 goto cleanup;
     838             :         }
     839             : 
     840         169 :         if (PG(open_basedir) && *PG(open_basedir)) {
     841           0 :                 sqlite3_set_authorizer(H->db, authorizer, NULL);
     842             :         }
     843             : 
     844         169 :         if (driver_options) {
     845           3 :                 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
     846             :         }
     847         169 :         sqlite3_busy_timeout(H->db, timeout * 1000);
     848             : 
     849         169 :         dbh->alloc_own_columns = 1;
     850         169 :         dbh->max_escaped_char_length = 2;
     851             : 
     852         169 :         ret = 1;
     853             :         
     854             : cleanup:
     855         170 :         dbh->methods = &sqlite_methods;
     856             :         
     857         170 :         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             :  */

Generated by: LCOV version 1.10

Generated at Tue, 25 Nov 2014 09:11:00 +0000 (41 hours ago)

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