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-21 Instrumented lines: 345
Code covered: 74.8 % Executed lines: 258
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:05 +0000 (3 days ago)

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