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

LTP GCOV extension - code coverage report
Current view: directory - pdo_sqlite - sqlite_driver.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 348
Code covered: 36.5 % Executed lines: 127
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:35 +0000 (33 hours ago)

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