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 - sqlite - sqlite.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 1329
Code covered: 71.4 % Executed lines: 949
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                 :    | Authors: Wez Furlong <wez@thebrainroom.com>                          |
      16                 :    |          Tal Peer <tal@php.net>                                      |
      17                 :    |          Marcus Boerger <helly@php.net>                              |
      18                 :    +----------------------------------------------------------------------+
      19                 : 
      20                 :    $Id: sqlite.c 289587 2009-10-12 19:04:00Z felipe $
      21                 : */
      22                 : 
      23                 : #ifdef HAVE_CONFIG_H
      24                 : #include "config.h"
      25                 : #endif
      26                 : 
      27                 : #define PHP_SQLITE_MODULE_VERSION       "2.0-dev"
      28                 : 
      29                 : #include "php.h"
      30                 : #include "php_ini.h"
      31                 : #include "ext/standard/info.h"
      32                 : #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
      33                 : #include "ext/session/php_session.h"
      34                 : #endif
      35                 : #include "php_sqlite.h"
      36                 : 
      37                 : #if HAVE_TIME_H
      38                 : # include <time.h>
      39                 : #endif
      40                 : #if HAVE_UNISTD_H
      41                 : #include <unistd.h>
      42                 : #endif
      43                 : 
      44                 : #include <sqlite.h>
      45                 : 
      46                 : #include "zend_exceptions.h"
      47                 : #include "zend_interfaces.h"
      48                 : 
      49                 : #if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
      50                 : extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
      51                 : extern PHPAPI zend_class_entry *spl_ce_Countable;
      52                 : #endif
      53                 : 
      54                 : #if PHP_SQLITE2_HAVE_PDO
      55                 : # include "pdo/php_pdo.h"
      56                 : # include "pdo/php_pdo_driver.h"
      57                 : extern pdo_driver_t pdo_sqlite2_driver;
      58                 : #endif
      59                 : 
      60                 : #ifndef safe_emalloc
      61                 : # define safe_emalloc(a,b,c) emalloc((a)*(b)+(c))
      62                 : #endif
      63                 : 
      64                 : ZEND_DECLARE_MODULE_GLOBALS(sqlite)
      65                 : static PHP_GINIT_FUNCTION(sqlite);
      66                 : 
      67                 : #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
      68                 : extern ps_module ps_mod_sqlite;
      69                 : #define ps_sqlite_ptr &ps_mod_sqlite
      70                 : #endif
      71                 : 
      72                 : extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
      73                 : extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
      74                 : 
      75                 : #define php_sqlite_encode_binary(in, n, out) sqlite_encode_binary((const unsigned char *)in, n, (unsigned char *)out)
      76                 : #define php_sqlite_decode_binary(in, out) in && *in ? sqlite_decode_binary((const unsigned char *)in, (unsigned char *)out) : 0
      77                 : 
      78                 : static int sqlite_count_elements(zval *object, long *count TSRMLS_DC);
      79                 : 
      80                 : static int le_sqlite_db, le_sqlite_result, le_sqlite_pdb;
      81                 : 
      82                 : static inline void php_sqlite_strtoupper(char *s)
      83               0 : {
      84               0 :         while (*s!='\0') {
      85               0 :                 *s = toupper(*s);
      86               0 :                 s++;
      87                 :         }
      88               0 : }
      89                 : 
      90                 : static inline void php_sqlite_strtolower(char *s)
      91               0 : {
      92               0 :         while (*s!='\0') {
      93               0 :                 *s = tolower(*s);
      94               0 :                 s++;
      95                 :         }
      96               0 : }
      97                 : 
      98                 : /* {{{ PHP_INI
      99                 :  */
     100                 : PHP_INI_BEGIN()
     101                 : STD_PHP_INI_ENTRY_EX("sqlite.assoc_case", "0", PHP_INI_ALL, OnUpdateLong, assoc_case, zend_sqlite_globals, sqlite_globals, display_link_numbers)
     102                 : PHP_INI_END()
     103                 : /* }}} */
     104                 : 
     105                 : #define DB_FROM_ZVAL(db, zv)    ZEND_FETCH_RESOURCE2(db, struct php_sqlite_db *, zv, -1, "sqlite database", le_sqlite_db, le_sqlite_pdb)
     106                 : 
     107                 : #define DB_FROM_OBJECT(db, object) \
     108                 :         { \
     109                 :                 sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
     110                 :                 db = obj->u.db; \
     111                 :                 if (!db) { \
     112                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "The database wasn't opened"); \
     113                 :                         RETURN_NULL(); \
     114                 :                 } \
     115                 :         }
     116                 : 
     117                 : #define RES_FROM_OBJECT(res, object) \
     118                 :         { \
     119                 :                 sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
     120                 :                 res = obj->u.res; \
     121                 :                 if (!res) { \
     122                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "No result set available"); \
     123                 :                         RETURN_NULL(); \
     124                 :                 } \
     125                 :         }
     126                 : 
     127                 : #define PHP_SQLITE_EMPTY_QUERY \
     128                 :         if (!sql_len || !*sql) { \
     129                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute empty query."); \
     130                 :                 RETURN_FALSE; \
     131                 :         }
     132                 : 
     133                 : struct php_sqlite_result {
     134                 :         struct php_sqlite_db *db;
     135                 :         sqlite_vm *vm;
     136                 :         int buffered;
     137                 :         int ncolumns;
     138                 :         int nrows;
     139                 :         int curr_row;
     140                 :         char **col_names;
     141                 :         int alloc_rows;
     142                 :         int mode;
     143                 :         char **table;
     144                 : };
     145                 : 
     146                 : struct php_sqlite_db {
     147                 :         sqlite *db;
     148                 :         int last_err_code;
     149                 :         zend_bool is_persistent;
     150                 :         long rsrc_id;
     151                 : 
     152                 :         HashTable callbacks;
     153                 : };
     154                 : 
     155                 : struct php_sqlite_agg_functions {
     156                 :         struct php_sqlite_db *db;
     157                 :         int is_valid;
     158                 :         zval *step;
     159                 :         zval *fini;
     160                 : };
     161                 : 
     162                 : static void php_sqlite_fetch_array(struct php_sqlite_result *res, int mode, zend_bool decode_binary, int move_next, zval *return_value TSRMLS_DC);
     163                 : static int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC);
     164                 : 
     165                 : enum { PHPSQLITE_ASSOC = 1, PHPSQLITE_NUM = 2, PHPSQLITE_BOTH = PHPSQLITE_ASSOC|PHPSQLITE_NUM };
     166                 : 
     167                 : zend_function_entry sqlite_functions[] = {
     168                 :         PHP_FE(sqlite_open, third_arg_force_ref)
     169                 :         PHP_FE(sqlite_popen, third_arg_force_ref)
     170                 :         PHP_FE(sqlite_close, NULL)
     171                 :         PHP_FE(sqlite_query, fourth_arg_force_ref)
     172                 :         PHP_FE(sqlite_exec, third_arg_force_ref)
     173                 :         PHP_FE(sqlite_array_query, NULL)
     174                 :         PHP_FE(sqlite_single_query, NULL)
     175                 :         PHP_FE(sqlite_fetch_array, NULL)
     176                 :         PHP_FE(sqlite_fetch_object, NULL)
     177                 :         PHP_FE(sqlite_fetch_single, NULL)
     178                 :         PHP_FALIAS(sqlite_fetch_string, sqlite_fetch_single, NULL)
     179                 :         PHP_FE(sqlite_fetch_all, NULL)
     180                 :         PHP_FE(sqlite_current, NULL)
     181                 :         PHP_FE(sqlite_column, NULL)
     182                 :         PHP_FE(sqlite_libversion, NULL)
     183                 :         PHP_FE(sqlite_libencoding, NULL)
     184                 :         PHP_FE(sqlite_changes, NULL)
     185                 :         PHP_FE(sqlite_last_insert_rowid, NULL)
     186                 :         PHP_FE(sqlite_num_rows, NULL)
     187                 :         PHP_FE(sqlite_num_fields, NULL)
     188                 :         PHP_FE(sqlite_field_name, NULL)
     189                 :         PHP_FE(sqlite_seek, NULL)
     190                 :         PHP_FE(sqlite_rewind, NULL)
     191                 :         PHP_FE(sqlite_next, NULL)
     192                 :         PHP_FE(sqlite_prev, NULL)
     193                 :         PHP_FE(sqlite_valid, NULL)
     194                 :         PHP_FALIAS(sqlite_has_more, sqlite_valid, NULL)
     195                 :         PHP_FE(sqlite_has_prev, NULL)
     196                 :         PHP_FE(sqlite_escape_string, NULL)
     197                 :         PHP_FE(sqlite_busy_timeout, NULL)
     198                 :         PHP_FE(sqlite_last_error, NULL)
     199                 :         PHP_FE(sqlite_error_string, NULL)
     200                 :         PHP_FE(sqlite_unbuffered_query, fourth_arg_force_ref)
     201                 :         PHP_FE(sqlite_create_aggregate, NULL)
     202                 :         PHP_FE(sqlite_create_function, NULL)
     203                 :         PHP_FE(sqlite_factory, third_arg_force_ref)
     204                 :         PHP_FE(sqlite_udf_encode_binary, NULL)
     205                 :         PHP_FE(sqlite_udf_decode_binary, NULL)
     206                 :         PHP_FE(sqlite_fetch_column_types, NULL)
     207                 :         {NULL, NULL, NULL}
     208                 : };
     209                 : 
     210                 : zend_function_entry sqlite_funcs_db[] = {
     211                 :         PHP_ME_MAPPING(__construct, sqlite_open, third_arg_force_ref, 0)
     212                 : /*      PHP_ME_MAPPING(close, sqlite_close, NULL, 0)*/
     213                 :         PHP_ME_MAPPING(query, sqlite_query, third_arg_force_ref, 0)
     214                 :         PHP_ME_MAPPING(queryExec, sqlite_exec, second_arg_force_ref, 0)
     215                 :         PHP_ME_MAPPING(arrayQuery, sqlite_array_query, NULL, 0)
     216                 :         PHP_ME_MAPPING(singleQuery, sqlite_single_query, NULL, 0)
     217                 :         PHP_ME_MAPPING(unbufferedQuery, sqlite_unbuffered_query, third_arg_force_ref, 0)
     218                 :         PHP_ME_MAPPING(lastInsertRowid, sqlite_last_insert_rowid, NULL, 0)
     219                 :         PHP_ME_MAPPING(changes, sqlite_changes, NULL, 0)
     220                 :         PHP_ME_MAPPING(createAggregate, sqlite_create_aggregate, NULL, 0)
     221                 :         PHP_ME_MAPPING(createFunction, sqlite_create_function, NULL, 0)
     222                 :         PHP_ME_MAPPING(busyTimeout, sqlite_busy_timeout, NULL, 0)
     223                 :         PHP_ME_MAPPING(lastError, sqlite_last_error, NULL, 0)
     224                 :         PHP_ME_MAPPING(fetchColumnTypes, sqlite_fetch_column_types, NULL, 0)
     225                 : /*      PHP_ME_MAPPING(error_string, sqlite_error_string, NULL, 0) static */
     226                 : /*      PHP_ME_MAPPING(escape_string, sqlite_escape_string, NULL, 0) static */
     227                 :         {NULL, NULL, NULL}
     228                 : };
     229                 : 
     230                 : zend_function_entry sqlite_funcs_query[] = {
     231                 :         PHP_ME_MAPPING(fetch, sqlite_fetch_array, NULL, 0)
     232                 :         PHP_ME_MAPPING(fetchObject, sqlite_fetch_object, NULL, 0)
     233                 :         PHP_ME_MAPPING(fetchSingle, sqlite_fetch_single, NULL, 0)
     234                 :         PHP_ME_MAPPING(fetchAll, sqlite_fetch_all, NULL, 0)
     235                 :         PHP_ME_MAPPING(column, sqlite_column, NULL, 0)
     236                 :         PHP_ME_MAPPING(numFields, sqlite_num_fields, NULL, 0)
     237                 :         PHP_ME_MAPPING(fieldName, sqlite_field_name, NULL, 0)
     238                 :         /* iterator */
     239                 :         PHP_ME_MAPPING(current, sqlite_current, NULL, 0)
     240                 :         PHP_ME_MAPPING(key, sqlite_key, NULL, 0)
     241                 :         PHP_ME_MAPPING(next, sqlite_next, NULL, 0)
     242                 :         PHP_ME_MAPPING(valid, sqlite_valid, NULL, 0)
     243                 :         PHP_ME_MAPPING(rewind, sqlite_rewind, NULL, 0)
     244                 :         /* countable */
     245                 :         PHP_ME_MAPPING(count, sqlite_num_rows, NULL, 0)
     246                 :         /* additional */
     247                 :         PHP_ME_MAPPING(prev, sqlite_prev, NULL, 0)
     248                 :         PHP_ME_MAPPING(hasPrev, sqlite_has_prev, NULL, 0)
     249                 :         PHP_ME_MAPPING(numRows, sqlite_num_rows, NULL, 0)
     250                 :         PHP_ME_MAPPING(seek, sqlite_seek, NULL, 0)
     251                 :         {NULL, NULL, NULL}
     252                 : };
     253                 : 
     254                 : zend_function_entry sqlite_funcs_ub_query[] = {
     255                 :         PHP_ME_MAPPING(fetch, sqlite_fetch_array, NULL, 0)
     256                 :         PHP_ME_MAPPING(fetchObject, sqlite_fetch_object, NULL, 0)
     257                 :         PHP_ME_MAPPING(fetchSingle, sqlite_fetch_single, NULL, 0)
     258                 :         PHP_ME_MAPPING(fetchAll, sqlite_fetch_all, NULL, 0)
     259                 :         PHP_ME_MAPPING(column, sqlite_column, NULL, 0)
     260                 :         PHP_ME_MAPPING(numFields, sqlite_num_fields, NULL, 0)
     261                 :         PHP_ME_MAPPING(fieldName, sqlite_field_name, NULL, 0)
     262                 :         /* iterator */
     263                 :         PHP_ME_MAPPING(current, sqlite_current, NULL, 0)
     264                 :         PHP_ME_MAPPING(next, sqlite_next, NULL, 0)
     265                 :         PHP_ME_MAPPING(valid, sqlite_valid, NULL, 0)
     266                 :         {NULL, NULL, NULL}
     267                 : };
     268                 : 
     269                 : zend_function_entry sqlite_funcs_exception[] = {
     270                 :         {NULL, NULL, NULL}
     271                 : };
     272                 : 
     273                 : /* Dependancies */
     274                 : static zend_module_dep sqlite_deps[] = {
     275                 : #if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
     276                 :         ZEND_MOD_REQUIRED("spl")
     277                 : #endif
     278                 : #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
     279                 :         ZEND_MOD_REQUIRED("session")
     280                 : #endif
     281                 : #ifdef PHP_SQLITE2_HAVE_PDO
     282                 :         ZEND_MOD_REQUIRED("pdo")
     283                 : #endif
     284                 :         {NULL, NULL, NULL}
     285                 : };
     286                 : 
     287                 : zend_module_entry sqlite_module_entry = {
     288                 : #if ZEND_MODULE_API_NO >= 20050922
     289                 :         STANDARD_MODULE_HEADER_EX, NULL,
     290                 :         sqlite_deps,
     291                 : #elif ZEND_MODULE_API_NO >= 20010901
     292                 :         STANDARD_MODULE_HEADER,
     293                 : #endif
     294                 :         "SQLite",
     295                 :         sqlite_functions,
     296                 :         PHP_MINIT(sqlite),
     297                 :         PHP_MSHUTDOWN(sqlite),
     298                 :         NULL,
     299                 :         PHP_RSHUTDOWN(sqlite),
     300                 :         PHP_MINFO(sqlite),
     301                 : #if ZEND_MODULE_API_NO >= 20010901
     302                 :         PHP_SQLITE_MODULE_VERSION,
     303                 : #endif
     304                 : #if ZEND_MODULE_API_NO >= 20060613
     305                 :         PHP_MODULE_GLOBALS(sqlite),
     306                 :         PHP_GINIT(sqlite),
     307                 :         NULL,
     308                 :         NULL,
     309                 :         STANDARD_MODULE_PROPERTIES_EX
     310                 : #else
     311                 :         STANDARD_MODULE_PROPERTIES
     312                 : #endif
     313                 : };
     314                 : 
     315                 : 
     316                 : #ifdef COMPILE_DL_SQLITE
     317                 : ZEND_GET_MODULE(sqlite)
     318                 : # ifdef PHP_WIN32
     319                 : # include "zend_arg_defs.c"
     320                 : # endif
     321                 : #endif
     322                 : 
     323                 : static int php_sqlite_callback_invalidator(struct php_sqlite_agg_functions *funcs TSRMLS_DC)
     324               3 : {
     325               3 :         if (!funcs->is_valid) {
     326               0 :                 return 0;
     327                 :         }
     328                 : 
     329               3 :         if (funcs->step) {
     330               3 :                 zval_ptr_dtor(&funcs->step);
     331               3 :                 funcs->step = NULL;
     332                 :         }
     333                 : 
     334               3 :         if (funcs->fini) {
     335               1 :                 zval_ptr_dtor(&funcs->fini);
     336               1 :                 funcs->fini = NULL;
     337                 :         }
     338                 : 
     339               3 :         funcs->is_valid = 0;
     340                 : 
     341               3 :         return 0;
     342                 : }
     343                 : 
     344                 : 
     345                 : static void php_sqlite_callback_dtor(void *pDest)
     346               3 : {
     347               3 :         struct php_sqlite_agg_functions *funcs = (struct php_sqlite_agg_functions*)pDest;
     348                 : 
     349               3 :         if (funcs->is_valid) {
     350                 :                 TSRMLS_FETCH();
     351                 : 
     352               3 :                 php_sqlite_callback_invalidator(funcs TSRMLS_CC);
     353                 :         }
     354               3 : }
     355                 : 
     356                 : static ZEND_RSRC_DTOR_FUNC(php_sqlite_db_dtor)
     357              51 : {
     358              51 :         if (rsrc->ptr) {
     359              51 :                 struct php_sqlite_db *db = (struct php_sqlite_db*)rsrc->ptr;
     360                 : 
     361              51 :                 sqlite_close(db->db);
     362                 : 
     363              51 :                 zend_hash_destroy(&db->callbacks);
     364                 : 
     365              51 :                 pefree(db, db->is_persistent);
     366                 : 
     367              51 :                 rsrc->ptr = NULL;
     368                 :         }
     369              51 : }
     370                 : 
     371                 : static void real_result_dtor(struct php_sqlite_result *res TSRMLS_DC)
     372              95 : {
     373                 :         int i, j, base;
     374                 : 
     375              95 :         if (res->vm) {
     376               0 :                 sqlite_finalize(res->vm, NULL);
     377                 :         }
     378                 : 
     379              95 :         if (res->table) {
     380              91 :                 if (!res->buffered && res->nrows) {
     381              50 :                         res->nrows = 1; /* only one row is stored */
     382                 :                 }
     383             216 :                 for (i = 0; i < res->nrows; i++) {
     384             125 :                         base = i * res->ncolumns;
     385             323 :                         for (j = 0; j < res->ncolumns; j++) {
     386             198 :                                 if (res->table[base + j] != NULL) {
     387             119 :                                         efree(res->table[base + j]);
     388                 :                                 }
     389                 :                         }
     390                 :                 }
     391              91 :                 efree(res->table);
     392                 :         }
     393              95 :         if (res->col_names) {
     394             264 :                 for (j = 0; j < res->ncolumns; j++) {
     395             169 :                         efree(res->col_names[j]);
     396                 :                 }
     397              95 :                 efree(res->col_names);
     398                 :         }
     399                 : 
     400              95 :         if (res->db) {
     401              95 :                 zend_list_delete(res->db->rsrc_id);
     402                 :         }
     403              95 :         efree(res);
     404              95 : }
     405                 : 
     406                 : static ZEND_RSRC_DTOR_FUNC(php_sqlite_result_dtor)
     407              30 : {
     408              30 :         struct php_sqlite_result *res = (struct php_sqlite_result *)rsrc->ptr;
     409              30 :         real_result_dtor(res TSRMLS_CC);
     410              30 : }
     411                 : 
     412                 : static int php_sqlite_forget_persistent_id_numbers(zend_rsrc_list_entry *rsrc TSRMLS_DC)
     413              40 : {
     414              40 :         struct php_sqlite_db *db = (struct php_sqlite_db*)rsrc->ptr;
     415                 : 
     416              40 :         if (Z_TYPE_P(rsrc) != le_sqlite_pdb) {
     417              40 :                 return 0;
     418                 :         }
     419                 : 
     420                 :         /* prevent bad mojo if someone tries to use a previously registered function in the next request */
     421               0 :         zend_hash_apply(&db->callbacks, (apply_func_t)php_sqlite_callback_invalidator TSRMLS_CC);
     422                 : 
     423               0 :         db->rsrc_id = FAILURE;
     424                 : 
     425                 :         /* don't leave pending commits hanging around */
     426               0 :         sqlite_exec(db->db, "ROLLBACK", NULL, NULL, NULL);
     427                 : 
     428               0 :         return 0;
     429                 : }
     430                 : 
     431                 : PHP_RSHUTDOWN_FUNCTION(sqlite)
     432           13584 : {
     433           13584 :         zend_hash_apply(&EG(persistent_list), (apply_func_t)php_sqlite_forget_persistent_id_numbers TSRMLS_CC);
     434           13584 :         return SUCCESS;
     435                 : }
     436                 : 
     437                 : /* {{{ PHP Function interface */
     438                 : static void php_sqlite_generic_function_callback(sqlite_func *func, int argc, const char **argv)
     439               7 : {
     440               7 :         zval *retval = NULL;
     441               7 :         zval ***zargs = NULL;
     442                 :         zval funcname;
     443                 :         int i, res;
     444               7 :         char *callable = NULL, *errbuf=NULL;
     445                 :         TSRMLS_FETCH();
     446                 : 
     447                 :         /* sanity check the args */
     448               7 :         if (argc == 0) {
     449               0 :                 sqlite_set_result_error(func, "not enough parameters", -1);
     450               0 :                 return;
     451                 :         }
     452                 : 
     453               7 :         ZVAL_STRING(&funcname, (char*)argv[0], 1);
     454                 : 
     455               7 :         if (!zend_make_callable(&funcname, &callable TSRMLS_CC)) {
     456               1 :                 spprintf(&errbuf, 0, "function `%s' is not a function name", callable);
     457               1 :                 sqlite_set_result_error(func, errbuf, -1);
     458               1 :                 efree(errbuf);
     459               1 :                 efree(callable);
     460               1 :                 zval_dtor(&funcname);
     461               1 :                 return;
     462                 :         }
     463                 : 
     464               6 :         if (argc > 1) {
     465               4 :                 zargs = (zval ***)safe_emalloc((argc - 1), sizeof(zval **), 0);
     466                 : 
     467               8 :                 for (i = 0; i < argc-1; i++) {
     468               4 :                         zargs[i] = emalloc(sizeof(zval *));
     469               4 :                         MAKE_STD_ZVAL(*zargs[i]);
     470               4 :                         ZVAL_STRING(*zargs[i], (char*)argv[i+1], 1);
     471                 :                 }
     472                 :         }
     473                 : 
     474               6 :         res = call_user_function_ex(EG(function_table),
     475                 :                         NULL,
     476                 :                         &funcname,
     477                 :                         &retval,
     478                 :                         argc-1,
     479                 :                         zargs,
     480                 :                         0, NULL TSRMLS_CC);
     481                 : 
     482               6 :         zval_dtor(&funcname);
     483                 : 
     484               6 :         if (res == SUCCESS) {
     485               6 :                 if (retval == NULL) {
     486               0 :                         sqlite_set_result_string(func, NULL, 0);
     487                 :                 } else {
     488               6 :                         switch (Z_TYPE_P(retval)) {
     489                 :                                 case IS_STRING:
     490               4 :                                         sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
     491               4 :                                         break;
     492                 :                                 case IS_LONG:
     493                 :                                 case IS_BOOL:
     494               0 :                                         sqlite_set_result_int(func, Z_LVAL_P(retval));
     495               0 :                                         break;
     496                 :                                 case IS_DOUBLE:
     497               0 :                                         sqlite_set_result_double(func, Z_DVAL_P(retval));
     498               0 :                                         break;
     499                 :                                 case IS_NULL:
     500                 :                                 default:
     501               2 :                                         sqlite_set_result_string(func, NULL, 0);
     502                 :                         }
     503                 :                 }
     504                 :         } else {
     505                 :                 char *errbuf;
     506               0 :                 spprintf(&errbuf, 0, "call_user_function_ex failed for function %s()", callable);
     507               0 :                 sqlite_set_result_error(func, errbuf, -1);
     508               0 :                 efree(errbuf);
     509                 :         }
     510                 : 
     511               6 :         efree(callable);
     512                 : 
     513               6 :         if (retval) {
     514               6 :                 zval_ptr_dtor(&retval);
     515                 :         }
     516                 : 
     517               6 :         if (zargs) {
     518               8 :                 for (i = 0; i < argc-1; i++) {
     519               4 :                         zval_ptr_dtor(zargs[i]);
     520               4 :                         efree(zargs[i]);
     521                 :                 }
     522               4 :                 efree(zargs);
     523                 :         }
     524                 : }
     525                 : /* }}} */
     526                 : 
     527                 : /* {{{ callback for sqlite_create_function */
     528                 : static void php_sqlite_function_callback(sqlite_func *func, int argc, const char **argv)
     529               4 : {
     530               4 :         zval *retval = NULL;
     531               4 :         zval ***zargs = NULL;
     532                 :         int i, res;
     533               4 :         struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
     534                 :         TSRMLS_FETCH();
     535                 : 
     536               4 :         if (!funcs->is_valid) {
     537               0 :                 sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
     538               0 :                 return;
     539                 :         }
     540                 : 
     541               4 :         if (argc > 0) {
     542               4 :                 zargs = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
     543                 : 
     544              14 :                 for (i = 0; i < argc; i++) {
     545              10 :                         zargs[i] = emalloc(sizeof(zval *));
     546              10 :                         MAKE_STD_ZVAL(*zargs[i]);
     547                 : 
     548              10 :                         if (argv[i] == NULL) {
     549               0 :                                 ZVAL_NULL(*zargs[i]);
     550                 :                         } else {
     551              10 :                                 ZVAL_STRING(*zargs[i], (char*)argv[i], 1);
     552                 :                         }
     553                 :                 }
     554                 :         }
     555                 : 
     556               4 :         res = call_user_function_ex(EG(function_table),
     557                 :                         NULL,
     558                 :                         funcs->step,
     559                 :                         &retval,
     560                 :                         argc,
     561                 :                         zargs,
     562                 :                         0, NULL TSRMLS_CC);
     563                 : 
     564               4 :         if (res == SUCCESS) {
     565               4 :                 if (retval == NULL) {
     566               0 :                         sqlite_set_result_string(func, NULL, 0);
     567                 :                 } else {
     568               4 :                         switch (Z_TYPE_P(retval)) {
     569                 :                                 case IS_STRING:
     570                 :                                         /* TODO: for binary results, need to encode the string */
     571               4 :                                         sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
     572               4 :                                         break;
     573                 :                                 case IS_LONG:
     574                 :                                 case IS_BOOL:
     575               0 :                                         sqlite_set_result_int(func, Z_LVAL_P(retval));
     576               0 :                                         break;
     577                 :                                 case IS_DOUBLE:
     578               0 :                                         sqlite_set_result_double(func, Z_DVAL_P(retval));
     579               0 :                                         break;
     580                 :                                 case IS_NULL:
     581                 :                                 default:
     582               0 :                                         sqlite_set_result_string(func, NULL, 0);
     583                 :                         }
     584                 :                 }
     585                 :         } else {
     586               0 :                 sqlite_set_result_error(func, "call_user_function_ex failed", -1);
     587                 :         }
     588                 : 
     589               4 :         if (retval) {
     590               4 :                 zval_ptr_dtor(&retval);
     591                 :         }
     592                 : 
     593               4 :         if (zargs) {
     594              14 :                 for (i = 0; i < argc; i++) {
     595              10 :                         zval_ptr_dtor(zargs[i]);
     596              10 :                         efree(zargs[i]);
     597                 :                 }
     598               4 :                 efree(zargs);
     599                 :         }
     600                 : }
     601                 : /* }}} */
     602                 : 
     603                 : /* {{{ callback for sqlite_create_aggregate: step function */
     604                 : static void php_sqlite_agg_step_function_callback(sqlite_func *func, int argc, const char **argv)
     605               3 : {
     606               3 :         zval *retval = NULL;
     607                 :         zval ***zargs;
     608                 :         zval **context_p;
     609                 :         int i, res, zargc;
     610               3 :         struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
     611                 :         TSRMLS_FETCH();
     612                 : 
     613               3 :         if (!funcs->is_valid) {
     614               0 :                 sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
     615               0 :                 return;
     616                 :         }
     617                 : 
     618                 :         /* sanity check the args */
     619               3 :         if (argc < 1) {
     620               0 :                 return;
     621                 :         }
     622                 : 
     623               3 :         zargc = argc + 1;
     624               3 :         zargs = (zval ***)safe_emalloc(zargc, sizeof(zval **), 0);
     625                 : 
     626                 :         /* first arg is always the context zval */
     627               3 :         context_p = (zval **)sqlite_aggregate_context(func, sizeof(*context_p));
     628                 : 
     629               3 :         if (*context_p == NULL) {
     630               1 :                 MAKE_STD_ZVAL(*context_p);
     631               1 :                 (*context_p)->is_ref = 1;
     632               1 :                 Z_TYPE_PP(context_p) = IS_NULL;
     633                 :         }
     634                 : 
     635               3 :         zargs[0] = context_p;
     636                 : 
     637                 :         /* copy the other args */
     638               6 :         for (i = 0; i < argc; i++) {
     639               3 :                 zargs[i+1] = emalloc(sizeof(zval *));
     640               3 :                 MAKE_STD_ZVAL(*zargs[i+1]);
     641               3 :                 if (argv[i] == NULL) {
     642               0 :                         ZVAL_NULL(*zargs[i+1]);
     643                 :                 } else {
     644               3 :                         ZVAL_STRING(*zargs[i+1], (char*)argv[i], 1);
     645                 :                 }
     646                 :         }
     647                 : 
     648               3 :         res = call_user_function_ex(EG(function_table),
     649                 :                         NULL,
     650                 :                         funcs->step,
     651                 :                         &retval,
     652                 :                         zargc,
     653                 :                         zargs,
     654                 :                         0, NULL TSRMLS_CC);
     655                 : 
     656               3 :         if (res != SUCCESS) {
     657               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "call_user_function_ex failed");
     658                 :         }
     659                 : 
     660               3 :         if (retval) {
     661               3 :                 zval_ptr_dtor(&retval);
     662                 :         }
     663                 : 
     664               3 :         if (zargs) {
     665               6 :                 for (i = 1; i < zargc; i++) {
     666               3 :                         zval_ptr_dtor(zargs[i]);
     667               3 :                         efree(zargs[i]);
     668                 :                 }
     669               3 :                 efree(zargs);
     670                 :         }
     671                 : }
     672                 : /* }}} */
     673                 : 
     674                 : /* {{{ callback for sqlite_create_aggregate: finalize function */
     675                 : static void php_sqlite_agg_fini_function_callback(sqlite_func *func)
     676               1 : {
     677               1 :         zval *retval = NULL;
     678                 :         int res;
     679               1 :         struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
     680                 :         zval **context_p;
     681                 :         TSRMLS_FETCH();
     682                 : 
     683               1 :         if (!funcs->is_valid) {
     684               0 :                 sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
     685               0 :                 return;
     686                 :         }
     687                 : 
     688               1 :         context_p = (zval **)sqlite_aggregate_context(func, sizeof(*context_p));
     689                 : 
     690               1 :         res = call_user_function_ex(EG(function_table),
     691                 :                         NULL,
     692                 :                         funcs->fini,
     693                 :                         &retval,
     694                 :                         1,
     695                 :                         &context_p,
     696                 :                         0, NULL TSRMLS_CC);
     697                 : 
     698               1 :         if (res == SUCCESS) {
     699               1 :                 if (retval == NULL) {
     700               0 :                         sqlite_set_result_string(func, NULL, 0);
     701                 :                 } else {
     702               1 :                         switch (Z_TYPE_P(retval)) {
     703                 :                                 case IS_STRING:
     704                 :                                         /* TODO: for binary results, need to encode the string */
     705               1 :                                         sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
     706               1 :                                         break;
     707                 :                                 case IS_LONG:
     708                 :                                 case IS_BOOL:
     709               0 :                                         sqlite_set_result_int(func, Z_LVAL_P(retval));
     710               0 :                                         break;
     711                 :                                 case IS_DOUBLE:
     712               0 :                                         sqlite_set_result_double(func, Z_DVAL_P(retval));
     713               0 :                                         break;
     714                 :                                 case IS_NULL:
     715                 :                                 default:
     716               0 :                                         sqlite_set_result_string(func, NULL, 0);
     717                 :                         }
     718                 :                 }
     719                 :         } else {
     720               0 :                 sqlite_set_result_error(func, "call_user_function_ex failed", -1);
     721                 :         }
     722                 : 
     723               1 :         if (retval) {
     724               1 :                 zval_ptr_dtor(&retval);
     725                 :         }
     726                 : 
     727               1 :         zval_ptr_dtor(context_p);
     728                 : }
     729                 : /* }}} */
     730                 : 
     731                 : /* {{{ Authorization Callback */
     732                 : static int php_sqlite_authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
     733                 :                 const char *arg5, const char *arg6)
     734               0 : {
     735               0 :         switch (access_type) {
     736                 :                 case SQLITE_COPY:
     737               0 :                         if (strncmp(arg4, ":memory:", sizeof(":memory:") - 1)) {
     738                 :                                 TSRMLS_FETCH();
     739               0 :                                 if (PG(safe_mode) && (!php_checkuid(arg4, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
     740               0 :                                         return SQLITE_DENY;
     741                 :                                 }
     742                 : 
     743               0 :                                 if (php_check_open_basedir(arg4 TSRMLS_CC)) {
     744               0 :                                         return SQLITE_DENY;
     745                 :                                 }
     746                 :                         }
     747               0 :                         return SQLITE_OK;
     748                 : #ifdef SQLITE_ATTACH
     749                 :                 case SQLITE_ATTACH:
     750               0 :                         if (strncmp(arg3, ":memory:", sizeof(":memory:") - 1)) {
     751                 :                                 TSRMLS_FETCH();
     752               0 :                                 if (PG(safe_mode) && (!php_checkuid(arg3, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
     753               0 :                                         return SQLITE_DENY;
     754                 :                                 }
     755                 : 
     756               0 :                                 if (php_check_open_basedir(arg3 TSRMLS_CC)) {
     757               0 :                                         return SQLITE_DENY;
     758                 :                                 }
     759                 :                         }
     760               0 :                         return SQLITE_OK;
     761                 : #endif
     762                 : 
     763                 :                 default:
     764                 :                         /* access allowed */
     765               0 :                         return SQLITE_OK;
     766                 :         }
     767                 : }
     768                 : /* }}} */
     769                 : 
     770                 : /* {{{ OO init/structure stuff */
     771                 : #define REGISTER_SQLITE_CLASS(name, c_name, parent) \
     772                 :         { \
     773                 :                 zend_class_entry ce; \
     774                 :                 INIT_CLASS_ENTRY(ce, "SQLite" # name, sqlite_funcs_ ## c_name); \
     775                 :                 ce.create_object = sqlite_object_new_ ## c_name; \
     776                 :                 sqlite_ce_ ## c_name = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
     777                 :                 memcpy(&sqlite_object_handlers_ ## c_name, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
     778                 :                 sqlite_object_handlers_ ## c_name.clone_obj = NULL; \
     779                 :                 sqlite_ce_ ## c_name->ce_flags |= ZEND_ACC_FINAL_CLASS; \
     780                 :         }
     781                 : 
     782                 : zend_class_entry *sqlite_ce_db, *sqlite_ce_exception;
     783                 : zend_class_entry *sqlite_ce_query, *sqlite_ce_ub_query;
     784                 : 
     785                 : static zend_object_handlers sqlite_object_handlers_db;
     786                 : static zend_object_handlers sqlite_object_handlers_query;
     787                 : static zend_object_handlers sqlite_object_handlers_ub_query;
     788                 : static zend_object_handlers sqlite_object_handlers_exception;
     789                 : 
     790                 : typedef enum {
     791                 :         is_db,
     792                 :         is_result
     793                 : } sqlite_obj_type;
     794                 : 
     795                 : typedef struct _sqlite_object {
     796                 :         zend_object       std;
     797                 :         sqlite_obj_type   type;
     798                 :         union {
     799                 :                 struct php_sqlite_db     *db;
     800                 :                 struct php_sqlite_result *res;
     801                 :                 void *ptr;
     802                 :         } u;
     803                 : } sqlite_object;
     804                 : 
     805                 : static int sqlite_free_persistent(zend_rsrc_list_entry *le, void *ptr TSRMLS_DC)
     806               0 : {
     807               0 :         return le->ptr == ptr ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_KEEP;
     808                 : }
     809                 : 
     810                 : static void sqlite_object_free_storage(void *object TSRMLS_DC)
     811              65 : {
     812              65 :         sqlite_object *intern = (sqlite_object *)object;
     813                 : 
     814              65 :         zend_object_std_dtor(&intern->std TSRMLS_CC);
     815                 : 
     816              65 :         if (intern->u.ptr) {
     817              64 :                 if (intern->type == is_db) {
     818              25 :                         if (intern->u.db->rsrc_id) {
     819              25 :                                 zend_list_delete(intern->u.db->rsrc_id);
     820              25 :                                 zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) sqlite_free_persistent, &intern->u.ptr TSRMLS_CC);
     821                 :                         }
     822                 :                 } else {
     823              39 :                         real_result_dtor(intern->u.res TSRMLS_CC);
     824                 :                 }
     825                 :         }
     826                 : 
     827              65 :         efree(object);
     828              65 : }
     829                 : 
     830                 : static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC)
     831              65 : {
     832                 :         sqlite_object *intern;
     833                 :         zval *tmp;
     834                 : 
     835              65 :         intern = emalloc(sizeof(sqlite_object));
     836              65 :         memset(intern, 0, sizeof(sqlite_object));
     837                 : 
     838              65 :         zend_object_std_init(&intern->std, class_type TSRMLS_CC);
     839              65 :         zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
     840                 : 
     841              65 :         retval->handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) sqlite_object_free_storage, NULL TSRMLS_CC);
     842              65 :         retval->handlers = handlers;
     843              65 : }
     844                 : 
     845                 : static zend_object_value sqlite_object_new_db(zend_class_entry *class_type TSRMLS_DC)
     846              25 : {
     847                 :         zend_object_value retval;
     848                 : 
     849              25 :         sqlite_object_new(class_type, &sqlite_object_handlers_db, &retval TSRMLS_CC);
     850              25 :         return retval;
     851                 : }
     852                 : 
     853                 : static zend_object_value sqlite_object_new_query(zend_class_entry *class_type TSRMLS_DC)
     854              17 : {
     855                 :         zend_object_value retval;
     856                 : 
     857              17 :         sqlite_object_new(class_type, &sqlite_object_handlers_query, &retval TSRMLS_CC);
     858              17 :         return retval;
     859                 : }
     860                 : 
     861                 : static zend_object_value sqlite_object_new_ub_query(zend_class_entry *class_type TSRMLS_DC)
     862              23 : {
     863                 :         zend_object_value retval;
     864                 : 
     865              23 :         sqlite_object_new(class_type, &sqlite_object_handlers_ub_query, &retval TSRMLS_CC);
     866              23 :         return retval;
     867                 : }
     868                 : 
     869                 : static zend_object_value sqlite_object_new_exception(zend_class_entry *class_type TSRMLS_DC)
     870               0 : {
     871                 :         zend_object_value retval;
     872                 : 
     873               0 :         sqlite_object_new(class_type, &sqlite_object_handlers_exception, &retval TSRMLS_CC);
     874               0 :         return retval;
     875                 : }
     876                 : 
     877                 : #define SQLITE_REGISTER_OBJECT(_type, _object, _ptr) \
     878                 :         { \
     879                 :                 sqlite_object *obj; \
     880                 :                 obj = (sqlite_object*)zend_object_store_get_object(_object TSRMLS_CC); \
     881                 :                 obj->type = is_ ## _type; \
     882                 :                 obj->u._type = _ptr; \
     883                 :         }
     884                 : 
     885                 : static zend_class_entry *sqlite_get_ce_query(zval *object TSRMLS_DC)
     886               4 : {
     887               4 :         return sqlite_ce_query;
     888                 : }
     889                 : 
     890                 : static zend_class_entry *sqlite_get_ce_ub_query(zval *object TSRMLS_DC)
     891               5 : {
     892               5 :         return sqlite_ce_ub_query;
     893                 : }
     894                 : 
     895                 : static zval * sqlite_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
     896              40 : {
     897              40 :         if (!object) {
     898               0 :                 ALLOC_ZVAL(object);
     899                 :         }
     900              40 :         Z_TYPE_P(object) = IS_OBJECT;
     901              40 :         object_init_ex(object, pce);
     902              40 :         object->refcount = 1;
     903              40 :         object->is_ref = 1;
     904              40 :         return object;
     905                 : }
     906                 : 
     907                 : typedef struct _sqlite_object_iterator {
     908                 :         zend_object_iterator     it;
     909                 :         struct php_sqlite_result *res;
     910                 :         zval *value;
     911                 : } sqlite_object_iterator;
     912                 : 
     913                 : void sqlite_iterator_dtor(zend_object_iterator *iter TSRMLS_DC)
     914               6 : {
     915               6 :         zval *object = (zval*)((sqlite_object_iterator*)iter)->it.data;
     916                 : 
     917               6 :         if (((sqlite_object_iterator*)iter)->value) {
     918               0 :                 zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
     919               0 :                 ((sqlite_object_iterator*)iter)->value = NULL;
     920                 :         }
     921               6 :         zval_ptr_dtor(&object);
     922               6 :         efree(iter);
     923               6 : }
     924                 : 
     925                 : void sqlite_iterator_rewind(zend_object_iterator *iter TSRMLS_DC)
     926               2 : {
     927               2 :         struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
     928                 : 
     929               2 :         if (((sqlite_object_iterator*)iter)->value) {
     930               0 :                 zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
     931               0 :                 ((sqlite_object_iterator*)iter)->value = NULL;
     932                 :         }
     933               2 :         if (res) {
     934               2 :                 res->curr_row = 0;
     935                 :         }
     936               2 : }
     937                 : 
     938                 : int sqlite_iterator_valid(zend_object_iterator *iter TSRMLS_DC)
     939              21 : {
     940              21 :         struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
     941                 : 
     942              21 :         if (res && res->curr_row < res->nrows && res->nrows) { /* curr_row may be -1 */
     943              15 :                 return SUCCESS;
     944                 :         } else {
     945               6 :                 return FAILURE;
     946                 :         }
     947                 : }
     948                 : 
     949                 : void sqlite_iterator_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
     950              15 : {
     951              15 :         struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
     952                 : 
     953              15 :         *data = &((sqlite_object_iterator*)iter)->value;
     954              15 :         if (res && !**data) {
     955              15 :                 MAKE_STD_ZVAL(**data);
     956              15 :                 php_sqlite_fetch_array(res, res->mode, 1, 0, **data TSRMLS_CC);
     957                 :         }
     958                 : 
     959              15 : }
     960                 : 
     961                 : int sqlite_iterator_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
     962               3 : {
     963               3 :         struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
     964                 : 
     965               3 :         *str_key = NULL;
     966               3 :         *str_key_len = 0;
     967               3 :         *int_key = res ? res->curr_row : 0;
     968               3 :         return HASH_KEY_IS_LONG;
     969                 : }
     970                 : 
     971                 : void sqlite_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC)
     972              15 : {
     973              15 :         struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
     974                 : 
     975              15 :         if (((sqlite_object_iterator*)iter)->value) {
     976              15 :                 zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
     977              15 :                 ((sqlite_object_iterator*)iter)->value = NULL;
     978                 :         }
     979              15 :         if (res) {
     980              15 :                 if (!res->buffered && res->vm) {
     981               9 :                         php_sqlite_fetch(res TSRMLS_CC);
     982                 :                 }
     983              15 :                 if (res->curr_row >= res->nrows) {
     984                 :                         /* php_error_docref(NULL TSRMLS_CC, E_WARNING, "no more rows available"); */
     985               0 :                         return;
     986                 :                 }
     987                 : 
     988              15 :                 res->curr_row++;
     989                 :         }
     990                 : }
     991                 : 
     992                 : zend_object_iterator_funcs sqlite_ub_query_iterator_funcs = {
     993                 :         sqlite_iterator_dtor,
     994                 :         sqlite_iterator_valid,
     995                 :         sqlite_iterator_get_current_data,
     996                 :         sqlite_iterator_get_current_key,
     997                 :         sqlite_iterator_move_forward,
     998                 :         NULL
     999                 : };
    1000                 : 
    1001                 : zend_object_iterator_funcs sqlite_query_iterator_funcs = {
    1002                 :         sqlite_iterator_dtor,
    1003                 :         sqlite_iterator_valid,
    1004                 :         sqlite_iterator_get_current_data,
    1005                 :         sqlite_iterator_get_current_key,
    1006                 :         sqlite_iterator_move_forward,
    1007                 :         sqlite_iterator_rewind
    1008                 : };
    1009                 : 
    1010                 : zend_object_iterator *sqlite_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
    1011               6 : {
    1012               6 :         sqlite_object_iterator *iterator = emalloc(sizeof(sqlite_object_iterator));
    1013                 : 
    1014               6 :         sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC);
    1015                 : 
    1016               6 :         if (by_ref) {
    1017               0 :                 zend_error(E_RECOVERABLE_ERROR, "An iterator cannot be used with foreach by reference");
    1018                 :         }
    1019               6 :         object->refcount++;
    1020               6 :         iterator->it.data = (void*)object;
    1021               6 :         iterator->it.funcs = ce->iterator_funcs.funcs;
    1022               6 :         iterator->res = obj->u.res;
    1023               6 :         iterator->value = NULL;
    1024               6 :         return (zend_object_iterator*)iterator;
    1025                 : }
    1026                 : /* }}} */
    1027                 : 
    1028                 : static PHP_GINIT_FUNCTION(sqlite)
    1029           13565 : {
    1030           13565 :         sqlite_globals->assoc_case = 0;
    1031           13565 : }
    1032                 : 
    1033                 : PHP_MINIT_FUNCTION(sqlite)
    1034           13565 : {
    1035           13565 :         REGISTER_SQLITE_CLASS(Database,   db,        NULL);
    1036           13565 :         REGISTER_SQLITE_CLASS(Result,     query,     NULL);
    1037           13565 :         REGISTER_SQLITE_CLASS(Unbuffered, ub_query,  NULL);
    1038                 : #if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
    1039           13565 :         REGISTER_SQLITE_CLASS(Exception,  exception, spl_ce_RuntimeException);
    1040                 : #else
    1041                 :         REGISTER_SQLITE_CLASS(Exception,  exception, zend_exception_get_default(TSRMLS_C));
    1042                 : #endif
    1043                 : 
    1044           13565 :         sqlite_ce_db->ce_flags &= ~ZEND_ACC_FINAL_CLASS;
    1045           13565 :         sqlite_ce_db->constructor->common.fn_flags |= ZEND_ACC_FINAL;
    1046                 : 
    1047           13565 :         sqlite_object_handlers_query.get_class_entry = sqlite_get_ce_query;
    1048           13565 :         sqlite_object_handlers_ub_query.get_class_entry = sqlite_get_ce_ub_query;
    1049           13565 :         sqlite_object_handlers_ub_query.count_elements = sqlite_count_elements;
    1050                 : 
    1051           13565 :         sqlite_ce_ub_query->get_iterator = sqlite_get_iterator;
    1052           13565 :         sqlite_ce_ub_query->iterator_funcs.funcs = &sqlite_ub_query_iterator_funcs;
    1053                 : 
    1054                 : #if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
    1055           13565 :         zend_class_implements(sqlite_ce_query TSRMLS_CC, 2, zend_ce_iterator, spl_ce_Countable);
    1056                 : #else
    1057                 :         zend_class_implements(sqlite_ce_query TSRMLS_CC, 1, zend_ce_iterator);
    1058                 : #endif
    1059           13565 :         sqlite_ce_query->get_iterator = sqlite_get_iterator;
    1060           13565 :         sqlite_ce_query->iterator_funcs.funcs = &sqlite_query_iterator_funcs;
    1061                 : 
    1062           13565 :         REGISTER_INI_ENTRIES();
    1063                 : 
    1064                 : #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
    1065           13565 :         php_session_register_module(ps_sqlite_ptr);
    1066                 : #endif
    1067                 : 
    1068           13565 :         le_sqlite_db = zend_register_list_destructors_ex(php_sqlite_db_dtor, NULL, "sqlite database", module_number);
    1069           13565 :         le_sqlite_pdb = zend_register_list_destructors_ex(NULL, php_sqlite_db_dtor, "sqlite database (persistent)", module_number);
    1070           13565 :         le_sqlite_result = zend_register_list_destructors_ex(php_sqlite_result_dtor, NULL, "sqlite result", module_number);
    1071                 : 
    1072           13565 :         REGISTER_LONG_CONSTANT("SQLITE_BOTH", PHPSQLITE_BOTH, CONST_CS|CONST_PERSISTENT);
    1073           13565 :         REGISTER_LONG_CONSTANT("SQLITE_NUM",  PHPSQLITE_NUM, CONST_CS|CONST_PERSISTENT);
    1074           13565 :         REGISTER_LONG_CONSTANT("SQLITE_ASSOC",        PHPSQLITE_ASSOC, CONST_CS|CONST_PERSISTENT);
    1075                 : 
    1076           13565 :         REGISTER_LONG_CONSTANT("SQLITE_OK",                           SQLITE_OK, CONST_CS|CONST_PERSISTENT);
    1077           13565 :         REGISTER_LONG_CONSTANT("SQLITE_ERROR",                        SQLITE_ERROR, CONST_CS|CONST_PERSISTENT);
    1078           13565 :         REGISTER_LONG_CONSTANT("SQLITE_INTERNAL",             SQLITE_INTERNAL, CONST_CS|CONST_PERSISTENT);
    1079           13565 :         REGISTER_LONG_CONSTANT("SQLITE_PERM",                 SQLITE_PERM, CONST_CS|CONST_PERSISTENT);
    1080           13565 :         REGISTER_LONG_CONSTANT("SQLITE_ABORT",                        SQLITE_ABORT, CONST_CS|CONST_PERSISTENT);
    1081           13565 :         REGISTER_LONG_CONSTANT("SQLITE_BUSY",                 SQLITE_BUSY, CONST_CS|CONST_PERSISTENT);
    1082           13565 :         REGISTER_LONG_CONSTANT("SQLITE_LOCKED",                       SQLITE_LOCKED, CONST_CS|CONST_PERSISTENT);
    1083           13565 :         REGISTER_LONG_CONSTANT("SQLITE_NOMEM",                        SQLITE_NOMEM, CONST_CS|CONST_PERSISTENT);
    1084           13565 :         REGISTER_LONG_CONSTANT("SQLITE_READONLY",             SQLITE_READONLY, CONST_CS|CONST_PERSISTENT);
    1085           13565 :         REGISTER_LONG_CONSTANT("SQLITE_INTERRUPT",            SQLITE_INTERRUPT, CONST_CS|CONST_PERSISTENT);
    1086           13565 :         REGISTER_LONG_CONSTANT("SQLITE_IOERR",                        SQLITE_IOERR, CONST_CS|CONST_PERSISTENT);
    1087           13565 :         REGISTER_LONG_CONSTANT("SQLITE_CORRUPT",              SQLITE_CORRUPT, CONST_CS|CONST_PERSISTENT);
    1088           13565 :         REGISTER_LONG_CONSTANT("SQLITE_NOTFOUND",             SQLITE_NOTFOUND, CONST_CS|CONST_PERSISTENT);
    1089           13565 :         REGISTER_LONG_CONSTANT("SQLITE_FULL",                 SQLITE_FULL, CONST_CS|CONST_PERSISTENT);
    1090           13565 :         REGISTER_LONG_CONSTANT("SQLITE_CANTOPEN",             SQLITE_CANTOPEN, CONST_CS|CONST_PERSISTENT);
    1091           13565 :         REGISTER_LONG_CONSTANT("SQLITE_PROTOCOL",             SQLITE_PROTOCOL, CONST_CS|CONST_PERSISTENT);
    1092           13565 :         REGISTER_LONG_CONSTANT("SQLITE_EMPTY",                        SQLITE_EMPTY, CONST_CS|CONST_PERSISTENT);
    1093           13565 :         REGISTER_LONG_CONSTANT("SQLITE_SCHEMA",                       SQLITE_SCHEMA, CONST_CS|CONST_PERSISTENT);
    1094           13565 :         REGISTER_LONG_CONSTANT("SQLITE_TOOBIG",                       SQLITE_TOOBIG, CONST_CS|CONST_PERSISTENT);
    1095           13565 :         REGISTER_LONG_CONSTANT("SQLITE_CONSTRAINT",           SQLITE_CONSTRAINT, CONST_CS|CONST_PERSISTENT);
    1096           13565 :         REGISTER_LONG_CONSTANT("SQLITE_MISMATCH",             SQLITE_MISMATCH, CONST_CS|CONST_PERSISTENT);
    1097           13565 :         REGISTER_LONG_CONSTANT("SQLITE_MISUSE",                       SQLITE_MISUSE, CONST_CS|CONST_PERSISTENT);
    1098           13565 :         REGISTER_LONG_CONSTANT("SQLITE_NOLFS",                        SQLITE_NOLFS, CONST_CS|CONST_PERSISTENT);
    1099           13565 :         REGISTER_LONG_CONSTANT("SQLITE_AUTH",                 SQLITE_AUTH, CONST_CS|CONST_PERSISTENT);
    1100           13565 :         REGISTER_LONG_CONSTANT("SQLITE_NOTADB",                       SQLITE_NOTADB, CONST_CS|CONST_PERSISTENT);
    1101                 : #ifdef SQLITE_FORMAT
    1102           13565 :         REGISTER_LONG_CONSTANT("SQLITE_FORMAT",                       SQLITE_FORMAT, CONST_CS|CONST_PERSISTENT);
    1103                 : #endif
    1104           13565 :         REGISTER_LONG_CONSTANT("SQLITE_ROW",                  SQLITE_ROW, CONST_CS|CONST_PERSISTENT);
    1105           13565 :         REGISTER_LONG_CONSTANT("SQLITE_DONE",                 SQLITE_DONE, CONST_CS|CONST_PERSISTENT);
    1106                 : 
    1107                 : #ifdef PHP_SQLITE2_HAVE_PDO
    1108           13565 :     if (FAILURE == php_pdo_register_driver(&pdo_sqlite2_driver)) {
    1109               0 :         return FAILURE;
    1110                 :     }
    1111                 : #endif
    1112                 : 
    1113           13565 :         return SUCCESS;
    1114                 : }
    1115                 : 
    1116                 : PHP_MSHUTDOWN_FUNCTION(sqlite)
    1117           13598 : {
    1118           13598 :         UNREGISTER_INI_ENTRIES();
    1119                 : 
    1120                 : #ifdef PHP_SQLITE2_HAVE_PDO
    1121           13598 :     php_pdo_unregister_driver(&pdo_sqlite2_driver);
    1122                 : #endif
    1123                 : 
    1124           13598 :         return SUCCESS;
    1125                 : }
    1126                 : 
    1127                 : PHP_MINFO_FUNCTION(sqlite)
    1128               6 : {
    1129               6 :         php_info_print_table_start();
    1130               6 :         php_info_print_table_header(2, "SQLite support", "enabled");
    1131               6 :         php_info_print_table_row(2, "PECL Module version", PHP_SQLITE_MODULE_VERSION " $Id: sqlite.c 289587 2009-10-12 19:04:00Z felipe $");
    1132               6 :         php_info_print_table_row(2, "SQLite Library", sqlite_libversion());
    1133               6 :         php_info_print_table_row(2, "SQLite Encoding", sqlite_libencoding());
    1134               6 :         php_info_print_table_end();
    1135                 : 
    1136               6 :         DISPLAY_INI_ENTRIES();
    1137               6 : }
    1138                 : 
    1139                 : static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *persistent_id, zval *return_value, zval *errmsg, zval *object TSRMLS_DC)
    1140              51 : {
    1141              51 :         char *errtext = NULL;
    1142              51 :         sqlite *sdb = NULL;
    1143              51 :         struct php_sqlite_db *db = NULL;
    1144                 : 
    1145              51 :         sdb = sqlite_open(filename, mode, &errtext);
    1146                 : 
    1147              51 :         if (sdb == NULL) {
    1148                 : 
    1149               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1150                 : 
    1151               0 :                 if (errmsg) {
    1152               0 :                         ZVAL_STRING(errmsg, errtext, 1);
    1153                 :                 }
    1154                 : 
    1155               0 :                 sqlite_freemem(errtext);
    1156                 : 
    1157                 :                 /* if object is not an object then we're called from the factory() function */
    1158               0 :                 if (object && Z_TYPE_P(object) != IS_OBJECT) {
    1159               0 :                         RETVAL_NULL();
    1160                 :                 } else {
    1161               0 :                         RETVAL_FALSE;
    1162                 :                 }
    1163               0 :                 return NULL;
    1164                 :         }
    1165                 : 
    1166              51 :         db = (struct php_sqlite_db *)pemalloc(sizeof(struct php_sqlite_db), persistent_id ? 1 : 0);
    1167              51 :         db->is_persistent = persistent_id ? 1 : 0;
    1168              51 :         db->last_err_code = SQLITE_OK;
    1169              51 :         db->db = sdb;
    1170                 : 
    1171              51 :         zend_hash_init(&db->callbacks, 0, NULL, php_sqlite_callback_dtor, db->is_persistent);
    1172                 : 
    1173                 :         /* register the PHP functions */
    1174              51 :         sqlite_create_function(sdb, "php", -1, php_sqlite_generic_function_callback, 0);
    1175                 : 
    1176                 :         /* set default busy handler; keep retrying up until 1 minute has passed,
    1177                 :          * then fail with a busy status code */
    1178              51 :         sqlite_busy_timeout(sdb, 60000);
    1179                 : 
    1180                 :         /* authorizer hook so we can enforce safe mode
    1181                 :          * Note: the declaration of php_sqlite_authorizer is correct for 2.8.2 of libsqlite,
    1182                 :          * and IS backwards binary compatible with earlier versions */
    1183              51 :         if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
    1184               0 :                 sqlite_set_authorizer(sdb, php_sqlite_authorizer, NULL);
    1185                 :         }
    1186                 : 
    1187              51 :         db->rsrc_id = ZEND_REGISTER_RESOURCE(object ? NULL : return_value, db, persistent_id ? le_sqlite_pdb : le_sqlite_db);
    1188              51 :         if (object) {
    1189                 :                 /* if object is not an object then we're called from the factory() function */
    1190              25 :                 if (Z_TYPE_P(object) != IS_OBJECT) {
    1191               1 :                         sqlite_instanciate(sqlite_ce_db, object TSRMLS_CC);
    1192                 :                 }
    1193                 :                 /* and now register the object */
    1194              25 :                 SQLITE_REGISTER_OBJECT(db, object, db)
    1195                 :         }
    1196                 : 
    1197              51 :         if (persistent_id) {
    1198                 :                 zend_rsrc_list_entry le;
    1199                 : 
    1200               0 :                 Z_TYPE(le) = le_sqlite_pdb;
    1201               0 :                 le.ptr = db;
    1202                 : 
    1203               0 :                 if (FAILURE == zend_hash_update(&EG(persistent_list), persistent_id,
    1204                 :                                         strlen(persistent_id)+1,
    1205                 :                                         (void *)&le, sizeof(le), NULL)) {
    1206               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent resource");
    1207                 :                 }
    1208                 :         }
    1209                 : 
    1210              51 :         return db;
    1211                 : }
    1212                 : 
    1213                 : /* {{{ proto resource sqlite_popen(string filename [, int mode [, string &error_message]])
    1214                 :    Opens a persistent handle to a SQLite database. Will create the database if it does not exist. */
    1215                 : PHP_FUNCTION(sqlite_popen)
    1216               0 : {
    1217               0 :         long mode = 0666;
    1218                 :         char *filename, *fullpath, *hashkey;
    1219                 :         int filename_len, hashkeylen;
    1220               0 :         zval *errmsg = NULL;
    1221               0 :         struct php_sqlite_db *db = NULL;
    1222                 :         zend_rsrc_list_entry *le;
    1223                 : 
    1224               0 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
    1225                 :                                 &filename, &filename_len, &mode, &errmsg)) {
    1226               0 :                 return;
    1227                 :         }
    1228               0 :         if (errmsg) {
    1229               0 :                 zval_dtor(errmsg);
    1230               0 :                 ZVAL_NULL(errmsg);
    1231                 :         }
    1232                 : 
    1233               0 :         if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
    1234                 :                 /* resolve the fully-qualified path name to use as the hash key */
    1235               0 :                 if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
    1236               0 :                         RETURN_FALSE;
    1237                 :                 }
    1238                 : 
    1239               0 :                 if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || 
    1240                 :                                 php_check_open_basedir(fullpath TSRMLS_CC)) {
    1241               0 :                         efree(fullpath);
    1242               0 :                         RETURN_FALSE;
    1243                 :                 }
    1244                 :         } else {
    1245               0 :                 fullpath = estrndup(filename, filename_len);
    1246                 :         }
    1247                 : 
    1248               0 :         hashkeylen = spprintf(&hashkey, 0, "sqlite_pdb_%s:%ld", fullpath, mode);
    1249                 : 
    1250                 :         /* do we have an existing persistent connection ? */
    1251               0 :         if (SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, hashkeylen+1, (void*)&le)) {
    1252               0 :                 if (Z_TYPE_P(le) == le_sqlite_pdb) {
    1253               0 :                         db = (struct php_sqlite_db*)le->ptr;
    1254                 : 
    1255               0 :                         if (db->rsrc_id == FAILURE) {
    1256                 :                                 /* give it a valid resource id for this request */
    1257               0 :                                 db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, le_sqlite_pdb);
    1258                 :                         } else {
    1259                 :                                 int type;
    1260                 :                                 /* sanity check to ensure that the resource is still a valid regular resource
    1261                 :                                  * number */
    1262               0 :                                 if (zend_list_find(db->rsrc_id, &type) == db) {
    1263                 :                                         /* already accessed this request; map it */
    1264               0 :                                         zend_list_addref(db->rsrc_id);
    1265               0 :                                         ZVAL_RESOURCE(return_value, db->rsrc_id);
    1266                 :                                 } else {
    1267               0 :                                         db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, le_sqlite_pdb);
    1268                 :                                 }
    1269                 :                         }
    1270                 : 
    1271                 :                         /* all set */
    1272               0 :                         goto done;
    1273                 :                 }
    1274                 : 
    1275               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Some other type of persistent resource is using this hash key!?");
    1276               0 :                 RETVAL_FALSE;
    1277               0 :                 goto done;
    1278                 :         }
    1279                 : 
    1280                 :         /* now we need to open the database */
    1281               0 :         php_sqlite_open(fullpath, (int)mode, hashkey, return_value, errmsg, NULL TSRMLS_CC);
    1282               0 : done:
    1283               0 :         efree(fullpath);
    1284               0 :         efree(hashkey);
    1285                 : }
    1286                 : /* }}} */
    1287                 : 
    1288                 : /* {{{ proto resource sqlite_open(string filename [, int mode [, string &error_message]])
    1289                 :    Opens a SQLite database. Will create the database if it does not exist. */
    1290                 : PHP_FUNCTION(sqlite_open)
    1291              50 : {
    1292              50 :         long mode = 0666;
    1293              50 :         char *filename, *fullpath = NULL;
    1294                 :         int filename_len;
    1295              50 :         zval *errmsg = NULL;
    1296              50 :         zval *object = getThis();
    1297                 : 
    1298              50 :         php_set_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception TSRMLS_CC);
    1299              50 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
    1300                 :                                 &filename, &filename_len, &mode, &errmsg)) {
    1301               0 :                 php_std_error_handling();
    1302               0 :                 return;
    1303                 :         }
    1304              50 :         if (errmsg) {
    1305               1 :                 zval_dtor(errmsg);
    1306               1 :                 ZVAL_NULL(errmsg);
    1307                 :         }
    1308                 : 
    1309              50 :         if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
    1310                 :                 /* resolve the fully-qualified path name to use as the hash key */
    1311               0 :                 if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
    1312               0 :                         php_std_error_handling();
    1313               0 :                         if (object) {
    1314               0 :                                 RETURN_NULL();
    1315                 :                         } else {
    1316               0 :                                 RETURN_FALSE;
    1317                 :                         }
    1318                 :                 }
    1319                 : 
    1320               0 :                 if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
    1321                 :                                 php_check_open_basedir(fullpath TSRMLS_CC)) {
    1322               0 :                         php_std_error_handling();
    1323               0 :                         efree(fullpath);
    1324               0 :                         if (object) {
    1325               0 :                                 RETURN_NULL();
    1326                 :                         } else {
    1327               0 :                                 RETURN_FALSE;
    1328                 :                         }
    1329                 :                 }
    1330                 :         }
    1331                 : 
    1332              50 :         php_sqlite_open(fullpath ? fullpath : filename, (int)mode, NULL, return_value, errmsg, object TSRMLS_CC);
    1333                 : 
    1334              50 :         if (fullpath) {
    1335               0 :                 efree(fullpath);
    1336                 :         }
    1337              50 :         php_std_error_handling();
    1338                 : }
    1339                 : /* }}} */
    1340                 : 
    1341                 : /* {{{ proto object sqlite_factory(string filename [, int mode [, string &error_message]])
    1342                 :    Opens a SQLite database and creates an object for it. Will create the database if it does not exist. */
    1343                 : PHP_FUNCTION(sqlite_factory)
    1344               3 : {
    1345               3 :         long mode = 0666;
    1346               3 :         char *filename, *fullpath = NULL;
    1347                 :         int filename_len;
    1348               3 :         zval *errmsg = NULL;
    1349                 : 
    1350               3 :         php_set_error_handling(EH_THROW, sqlite_ce_exception TSRMLS_CC);
    1351               3 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
    1352                 :                                 &filename, &filename_len, &mode, &errmsg)) {
    1353               2 :                 php_std_error_handling();
    1354               2 :                 RETURN_NULL();
    1355                 :         }
    1356               1 :         if (errmsg) {
    1357               0 :                 zval_dtor(errmsg);
    1358               0 :                 ZVAL_NULL(errmsg);
    1359                 :         }
    1360                 : 
    1361               1 :         if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
    1362                 :                 /* resolve the fully-qualified path name to use as the hash key */
    1363               1 :                 if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
    1364               0 :                         php_std_error_handling();
    1365               0 :                         RETURN_NULL();
    1366                 :                 }
    1367                 : 
    1368               1 :                 if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
    1369                 :                                 php_check_open_basedir(fullpath TSRMLS_CC)) {
    1370               0 :                         efree(fullpath);
    1371               0 :                         php_std_error_handling();
    1372               0 :                         RETURN_NULL();
    1373                 :                 }
    1374                 :         }
    1375                 : 
    1376               1 :         php_sqlite_open(fullpath ? fullpath : filename, (int)mode, NULL, return_value, errmsg, return_value TSRMLS_CC);
    1377               1 :         if (fullpath) {
    1378               1 :                 efree(fullpath);
    1379                 :         }
    1380               1 :         php_std_error_handling();
    1381                 : }
    1382                 : /* }}} */
    1383                 : 
    1384                 : /* {{{ proto void sqlite_busy_timeout(resource db, int ms)
    1385                 :    Set busy timeout duration. If ms <= 0, all busy handlers are disabled. */
    1386                 : PHP_FUNCTION(sqlite_busy_timeout)
    1387               0 : {
    1388                 :         zval *zdb;
    1389                 :         struct php_sqlite_db *db;
    1390                 :         long ms;
    1391               0 :         zval *object = getThis();
    1392                 : 
    1393               0 :         if (object) {
    1394               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ms)) {
    1395               0 :                         return;
    1396                 :                 }
    1397               0 :                 DB_FROM_OBJECT(db, object);
    1398                 :         } else {
    1399               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zdb, &ms)) {
    1400               0 :                         return;
    1401                 :                 }
    1402               0 :                 DB_FROM_ZVAL(db, &zdb);
    1403                 :         }
    1404                 : 
    1405               0 :         sqlite_busy_timeout(db->db, ms);
    1406                 : }
    1407                 : /* }}} */
    1408                 : 
    1409                 : /* {{{ proto void sqlite_close(resource db)
    1410                 :    Closes an open sqlite database. */
    1411                 : PHP_FUNCTION(sqlite_close)
    1412              22 : {
    1413                 :         zval *zdb;
    1414                 :         struct php_sqlite_db *db;
    1415              22 :         zval *object = getThis();
    1416                 : 
    1417              22 :         if (object) {
    1418               0 :                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Ignored, you must destruct the object instead");
    1419                 :         } else {
    1420              22 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
    1421               0 :                         return;
    1422                 :                 }
    1423              22 :                 DB_FROM_ZVAL(db, &zdb);
    1424                 :         }
    1425                 : 
    1426              22 :         zend_list_delete(Z_RESVAL_P(zdb));
    1427                 : }
    1428                 : /* }}} */
    1429                 : 
    1430                 : /* {{{ php_sqlite_fetch */
    1431                 : static int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC)
    1432             186 : {
    1433                 :         const char **rowdata, **colnames;
    1434                 :         int ret, i, base;
    1435             186 :         char *errtext = NULL;
    1436                 : 
    1437             261 : next_row:
    1438             261 :         ret = sqlite_step(rres->vm, &rres->ncolumns, &rowdata, &colnames);
    1439             261 :         if (!rres->nrows) {
    1440                 :                 /* first row - lets copy the column names */
    1441              95 :                 rres->col_names = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
    1442             264 :                 for (i = 0; i < rres->ncolumns; i++) {
    1443             169 :                         rres->col_names[i] = estrdup((char*)colnames[i]);
    1444                 : 
    1445             169 :                         if (SQLITE_G(assoc_case) == 1) {
    1446               0 :                                 php_sqlite_strtoupper(rres->col_names[i]);
    1447             169 :                         } else if (SQLITE_G(assoc_case) == 2) {
    1448               0 :                                 php_sqlite_strtolower(rres->col_names[i]);
    1449                 :                         }
    1450                 :                 }
    1451              95 :                 if (!rres->buffered) {
    1452                 :                         /* non buffered mode - also fetch memory for on single row */
    1453              59 :                         rres->table = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
    1454                 :                 }
    1455                 :         }
    1456                 : 
    1457             261 :         switch (ret) {
    1458                 :                 case SQLITE_ROW:
    1459             166 :                         if (rres->buffered) {
    1460                 :                                 /* add the row to our collection */
    1461              75 :                                 if (rres->nrows + 1 >= rres->alloc_rows) {
    1462              32 :                                         rres->alloc_rows = rres->alloc_rows ? rres->alloc_rows * 2 : 16;
    1463              32 :                                         rres->table = safe_erealloc(rres->table, rres->alloc_rows, rres->ncolumns*sizeof(char *), 0);
    1464                 :                                 }
    1465              75 :                                 base = rres->nrows * rres->ncolumns;
    1466             196 :                                 for (i = 0; i < rres->ncolumns; i++) {
    1467             121 :                                         if (rowdata[i]) {
    1468             113 :                                                 rres->table[base + i] = estrdup(rowdata[i]);
    1469                 :                                         } else {
    1470               8 :                                                 rres->table[base + i] = NULL;
    1471                 :                                         }
    1472                 :                                 }
    1473              75 :                                 rres->nrows++;
    1474              75 :                                 goto next_row;
    1475                 :                         } else {
    1476                 :                                 /* non buffered: only fetch one row but first free data if not first row */
    1477              91 :                                 if (rres->nrows++) {
    1478              93 :                                         for (i = 0; i < rres->ncolumns; i++) {
    1479              52 :                                                 if (rres->table[i]) {
    1480               8 :                                                         efree(rres->table[i]);
    1481                 :                                                 }
    1482                 :                                         }
    1483                 :                                 }
    1484             220 :                                 for (i = 0; i < rres->ncolumns; i++) {
    1485             129 :                                         if (rowdata[i]) {
    1486             124 :                                                 rres->table[i] = estrdup(rowdata[i]);
    1487                 :                                         } else {
    1488               5 :                                                 rres->table[i] = NULL;
    1489                 :                                         }
    1490                 :                                 }
    1491                 :                         }
    1492              91 :                         ret = SQLITE_OK;
    1493              91 :                         break;
    1494                 : 
    1495                 :                 case SQLITE_BUSY:
    1496                 :                 case SQLITE_ERROR:
    1497                 :                 case SQLITE_MISUSE:
    1498                 :                 case SQLITE_DONE:
    1499                 :                 default:
    1500              95 :                         if (rres->vm) {
    1501              95 :                                 ret = sqlite_finalize(rres->vm, &errtext);
    1502                 :                         }
    1503              95 :                         rres->vm = NULL;
    1504              95 :                         if (ret != SQLITE_OK) {
    1505               1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1506               1 :                                 sqlite_freemem(errtext);
    1507                 :                         }
    1508                 :                         break;
    1509                 :         }
    1510             186 :         rres->db->last_err_code = ret;
    1511                 : 
    1512             186 :         return ret;
    1513                 : }
    1514                 : /* }}} */
    1515                 : 
    1516                 : /* {{{ sqlite_query */
    1517                 : void sqlite_query(zval *object, struct php_sqlite_db *db, char *sql, long sql_len, int mode, int buffered, zval *return_value, struct php_sqlite_result **prres, zval *errmsg TSRMLS_DC)
    1518             100 : {
    1519                 :         struct php_sqlite_result res, *rres;
    1520                 :         int ret;
    1521             100 :         char *errtext = NULL;
    1522                 :         const char *tail;
    1523                 : 
    1524             100 :         memset(&res, 0, sizeof(res));
    1525             100 :         res.buffered = buffered;
    1526             100 :         res.mode = mode;
    1527                 : 
    1528             100 :         ret = sqlite_compile(db->db, sql, &tail, &res.vm, &errtext);
    1529             100 :         db->last_err_code = ret;
    1530                 : 
    1531             100 :         if (ret != SQLITE_OK) {
    1532               4 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1533               4 :                 if (errmsg) {
    1534               2 :                         ZVAL_STRING(errmsg, errtext, 1);
    1535                 :                 }
    1536               4 :                 sqlite_freemem(errtext);
    1537               4 :                 goto terminate;
    1538              96 :         } else if (!res.vm) { /* empty query */
    1539               5 : terminate:
    1540               5 :                 if (return_value) {
    1541               3 :                         RETURN_FALSE;
    1542                 :                 } else {
    1543               2 :                         return;
    1544                 :                 }
    1545                 :         }
    1546                 : 
    1547              95 :         if (!prres) {
    1548              69 :                 rres = NULL;
    1549              69 :                 prres = &rres;
    1550                 :         }
    1551              95 :         if (!*prres) {
    1552              69 :                 *prres = (struct php_sqlite_result*)emalloc(sizeof(**prres));
    1553                 :         }
    1554              95 :         memcpy(*prres, &res, sizeof(**prres));
    1555              95 :         (*prres)->db = db;
    1556              95 :         zend_list_addref(db->rsrc_id);
    1557                 : 
    1558                 : 
    1559                 :         /* now the result set is ready for stepping: get first row */
    1560              95 :         if (php_sqlite_fetch((*prres) TSRMLS_CC) != SQLITE_OK) {
    1561               1 :                 real_result_dtor((*prres) TSRMLS_CC);
    1562               1 :                 *prres = NULL;
    1563               1 :                 if (return_value) {
    1564               0 :                         RETURN_FALSE;
    1565                 :                 } else {
    1566               1 :                         return;
    1567                 :                 }
    1568                 :         }
    1569                 : 
    1570              94 :         (*prres)->curr_row = 0;
    1571                 : 
    1572              94 :         if (object) {
    1573                 :                 sqlite_object *obj;
    1574              39 :                 if (buffered) {
    1575              17 :                         sqlite_instanciate(sqlite_ce_query, return_value TSRMLS_CC);
    1576                 :                 } else {
    1577              22 :                         sqlite_instanciate(sqlite_ce_ub_query, return_value TSRMLS_CC);
    1578                 :                 }
    1579              39 :                 obj = (sqlite_object *) zend_object_store_get_object(return_value TSRMLS_CC);
    1580              39 :                 obj->type = is_result;
    1581              39 :                 obj->u.res = (*prres);
    1582              55 :         } else if (return_value) {
    1583              30 :                 ZEND_REGISTER_RESOURCE(object ? NULL : return_value, (*prres), le_sqlite_result);
    1584                 :         }
    1585                 : }
    1586                 : /* }}} */
    1587                 : 
    1588                 : /* {{{ proto resource sqlite_unbuffered_query(string query, resource db [ , int result_type [, string &error_message]])
    1589                 :    Executes a query that does not prefetch and buffer all data. */
    1590                 : PHP_FUNCTION(sqlite_unbuffered_query)
    1591              34 : {
    1592                 :         zval *zdb;
    1593                 :         struct php_sqlite_db *db;
    1594                 :         char *sql;
    1595                 :         int sql_len;
    1596              34 :         long mode = PHPSQLITE_BOTH;
    1597              34 :         char *errtext = NULL;
    1598              34 :         zval *errmsg = NULL;
    1599              34 :         zval *object = getThis();
    1600                 : 
    1601              34 :         if (object) {
    1602              22 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
    1603               0 :                         return;
    1604                 :                 }
    1605              22 :                 DB_FROM_OBJECT(db, object);
    1606                 :         } else {
    1607              12 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    1608                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
    1609                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
    1610               0 :                         return;
    1611                 :                 }
    1612              12 :                 DB_FROM_ZVAL(db, &zdb);
    1613                 :         }
    1614                 : 
    1615              34 :         if (errmsg) {
    1616               1 :                 zval_dtor(errmsg);
    1617               1 :                 ZVAL_NULL(errmsg);
    1618                 :         }
    1619                 : 
    1620              34 :         PHP_SQLITE_EMPTY_QUERY;
    1621                 : 
    1622                 :         /* avoid doing work if we can */
    1623              34 :         if (!return_value_used) {
    1624               0 :                 db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    1625                 : 
    1626               0 :                 if (db->last_err_code != SQLITE_OK) {
    1627               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1628               0 :                         if (errmsg) {
    1629               0 :                                 ZVAL_STRING(errmsg, errtext, 1);
    1630                 :                         }
    1631               0 :                         sqlite_freemem(errtext);
    1632                 :                 }
    1633               0 :                 return;
    1634                 :         }
    1635                 : 
    1636              34 :         sqlite_query(object, db, sql, sql_len, (int)mode, 0, return_value, NULL, errmsg TSRMLS_CC);
    1637                 : }
    1638                 : /* }}} */
    1639                 : 
    1640                 : /* {{{ proto resource sqlite_fetch_column_types(string table_name, resource db [, int result_type])
    1641                 :    Return an array of column types from a particular table. */
    1642                 : PHP_FUNCTION(sqlite_fetch_column_types)
    1643               2 : {
    1644                 :         zval *zdb;
    1645                 :         struct php_sqlite_db *db;
    1646                 :         char *tbl, *sql;
    1647                 :         int tbl_len;
    1648               2 :         char *errtext = NULL;
    1649               2 :         zval *object = getThis();
    1650                 :         struct php_sqlite_result res;
    1651                 :         const char **rowdata, **colnames, *tail;
    1652                 :         int i, ncols;
    1653               2 :         long result_type = PHPSQLITE_ASSOC;
    1654                 : 
    1655               2 :         if (object) {
    1656               1 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &tbl, &tbl_len, &result_type)) {
    1657               0 :                         return;
    1658                 :                 }
    1659               1 :                 DB_FROM_OBJECT(db, object);
    1660                 :         } else {
    1661               1 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    1662                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &tbl, &tbl_len, &zdb, &result_type) &&
    1663                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &tbl, &tbl_len, &result_type)) {
    1664               0 :                         return;
    1665                 :                 }
    1666               1 :                 DB_FROM_ZVAL(db, &zdb);
    1667                 :         }
    1668                 : 
    1669               2 :         if (!(sql = sqlite_mprintf("SELECT * FROM '%q' LIMIT 1", tbl))) {
    1670               0 :                 RETURN_FALSE;
    1671                 :         }
    1672                 : 
    1673               2 :         sqlite_exec(db->db, "PRAGMA show_datatypes = ON", NULL, NULL, NULL);
    1674                 : 
    1675               2 :         db->last_err_code = sqlite_compile(db->db, sql, &tail, &res.vm, &errtext);
    1676                 : 
    1677               2 :         sqlite_freemem(sql);
    1678                 : 
    1679               2 :         if (db->last_err_code != SQLITE_OK) {
    1680               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1681               0 :                 sqlite_freemem(errtext);
    1682               0 :                 RETVAL_FALSE;
    1683               0 :                 goto done;
    1684                 :         }
    1685                 : 
    1686               2 :         sqlite_step(res.vm, &ncols, &rowdata, &colnames);
    1687                 : 
    1688               2 :         array_init(return_value);
    1689                 : 
    1690              10 :         for (i = 0; i < ncols; i++) {
    1691               8 :                 if (result_type == PHPSQLITE_ASSOC) {
    1692               8 :                         char *colname = estrdup((char *)colnames[i]);
    1693                 : 
    1694               8 :                         if (SQLITE_G(assoc_case) == 1) {
    1695               0 :                                 php_sqlite_strtoupper(colname);
    1696               8 :                         } else if (SQLITE_G(assoc_case) == 2) {
    1697               0 :                                 php_sqlite_strtolower(colname);
    1698                 :                         }
    1699                 : 
    1700               8 :                         add_assoc_string(return_value, colname, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
    1701               8 :                         efree(colname);
    1702                 :                 }
    1703               8 :                 if (result_type == PHPSQLITE_NUM) {
    1704               0 :                         add_index_string(return_value, i, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
    1705                 :                 }
    1706                 :         }
    1707               2 :         if (res.vm) {
    1708               2 :                 sqlite_finalize(res.vm, NULL);
    1709                 :         }
    1710               2 : done:
    1711               2 :         sqlite_exec(db->db, "PRAGMA show_datatypes = OFF", NULL, NULL, NULL);
    1712                 : }
    1713                 : /* }}} */
    1714                 : 
    1715                 : /* {{{ proto resource sqlite_query(string query, resource db [, int result_type [, string &error_message]])
    1716                 :    Executes a query against a given database and returns a result handle. */
    1717                 : PHP_FUNCTION(sqlite_query)
    1718             209 : {
    1719                 :         zval *zdb;
    1720                 :         struct php_sqlite_db *db;
    1721                 :         char *sql;
    1722                 :         int sql_len;
    1723             209 :         long mode = PHPSQLITE_BOTH;
    1724             209 :         char *errtext = NULL;
    1725             209 :         zval *errmsg = NULL;
    1726             209 :         zval *object = getThis();
    1727                 : 
    1728             209 :         if (object) {
    1729             106 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
    1730               0 :                         return;
    1731                 :                 }
    1732             106 :                 DB_FROM_OBJECT(db, object);
    1733                 :         } else {
    1734             103 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    1735                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
    1736                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
    1737               0 :                         return;
    1738                 :                 }
    1739             103 :                 DB_FROM_ZVAL(db, &zdb);
    1740                 :         }
    1741                 : 
    1742             209 :         if (errmsg) {
    1743               1 :                 zval_dtor(errmsg);
    1744               1 :                 ZVAL_NULL(errmsg);
    1745                 :         }
    1746                 : 
    1747             209 :         PHP_SQLITE_EMPTY_QUERY;
    1748                 : 
    1749                 :         /* avoid doing work if we can */
    1750             209 :         if (!return_value_used) {
    1751             171 :                 db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    1752                 : 
    1753             171 :                 if (db->last_err_code != SQLITE_OK) {
    1754               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1755               0 :                         if (errmsg) {
    1756               0 :                                 ZVAL_STRING(errmsg, errtext, 1);
    1757                 :                         }
    1758               0 :                         sqlite_freemem(errtext);
    1759                 :                 }
    1760             171 :                 return;
    1761                 :         }
    1762                 : 
    1763              38 :         sqlite_query(object, db, sql, sql_len, (int)mode, 1, return_value, NULL, errmsg TSRMLS_CC);
    1764                 : }
    1765                 : /* }}} */
    1766                 : 
    1767                 : /* {{{ proto boolean sqlite_exec(string query, resource db[, string &error_message])
    1768                 :    Executes a result-less query against a given database */
    1769                 : PHP_FUNCTION(sqlite_exec)
    1770               0 : {
    1771                 :         zval *zdb;
    1772                 :         struct php_sqlite_db *db;
    1773                 :         char *sql;
    1774                 :         int sql_len;
    1775               0 :         char *errtext = NULL;
    1776               0 :         zval *errmsg = NULL;
    1777               0 :         zval *object = getThis();
    1778                 : 
    1779               0 :         if (object) {
    1780               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &sql, &sql_len, &errmsg)) {
    1781               0 :                         return;
    1782                 :                 }
    1783               0 :                 DB_FROM_OBJECT(db, object);
    1784                 :         } else {
    1785               0 :                 if(FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    1786                 :                         ZEND_NUM_ARGS() TSRMLS_CC, "sr", &sql, &sql_len, &zdb) &&
    1787                 :                    FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z/", &zdb, &sql, &sql_len, &errmsg)) {
    1788               0 :                         return;
    1789                 :                 }
    1790               0 :                 DB_FROM_ZVAL(db, &zdb);
    1791                 :         }
    1792                 : 
    1793               0 :         if (errmsg) {
    1794               0 :                 zval_dtor(errmsg);
    1795               0 :                 ZVAL_NULL(errmsg);
    1796                 :         }
    1797                 : 
    1798               0 :         PHP_SQLITE_EMPTY_QUERY;
    1799                 : 
    1800               0 :         db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    1801                 : 
    1802               0 :         if (db->last_err_code != SQLITE_OK) {
    1803               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1804               0 :                 if (errmsg) {
    1805               0 :                         ZVAL_STRING(errmsg, errtext, 1);
    1806                 :                 }
    1807               0 :                 sqlite_freemem(errtext);
    1808               0 :                 RETURN_FALSE;
    1809                 :         }
    1810                 : 
    1811               0 :         RETURN_TRUE;
    1812                 : }
    1813                 : /* }}} */
    1814                 : 
    1815                 : /* {{{ php_sqlite_fetch_array */
    1816                 : static void php_sqlite_fetch_array(struct php_sqlite_result *res, int mode, zend_bool decode_binary, int move_next, zval *return_value TSRMLS_DC)
    1817             157 : {
    1818             157 :         int j, n = res->ncolumns, buffered = res->buffered;
    1819                 :         const char **rowdata, **colnames;
    1820                 : 
    1821                 :         /* check range of the row */
    1822             157 :         if (res->curr_row >= res->nrows) {
    1823                 :                 /* no more */
    1824              10 :                 RETURN_FALSE;
    1825                 :         }
    1826             147 :         colnames = (const char**)res->col_names;
    1827             147 :         if (res->buffered) {
    1828              94 :                 rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
    1829                 :         } else {
    1830              53 :                 rowdata = (const char**)res->table;
    1831                 :         }
    1832                 : 
    1833                 :         /* now populate the result */
    1834             147 :         array_init(return_value);
    1835                 : 
    1836             344 :         for (j = 0; j < n; j++) {
    1837                 :                 zval *decoded;
    1838             197 :                 MAKE_STD_ZVAL(decoded);
    1839                 : 
    1840             197 :                 if (rowdata[j] == NULL) {
    1841              11 :                         ZVAL_NULL(decoded);
    1842             188 :                 } else if (decode_binary && rowdata[j][0] == '\x01') {
    1843               2 :                         Z_STRVAL_P(decoded) = emalloc(strlen(rowdata[j]));
    1844               2 :                         Z_STRLEN_P(decoded) = php_sqlite_decode_binary(rowdata[j]+1, Z_STRVAL_P(decoded));
    1845               2 :                         Z_STRVAL_P(decoded)[Z_STRLEN_P(decoded)] = '\0';
    1846               2 :                         Z_TYPE_P(decoded) = IS_STRING;
    1847               2 :                         if (!buffered) {
    1848               0 :                                 efree((char*)rowdata[j]);
    1849               0 :                                 rowdata[j] = NULL;
    1850                 :                         }
    1851                 :                 } else {
    1852             184 :                         ZVAL_STRING(decoded, (char*)rowdata[j], buffered);
    1853             184 :                         if (!buffered) {
    1854              70 :                                 rowdata[j] = NULL;
    1855                 :                         }
    1856                 :                 }
    1857                 : 
    1858             197 :                 if (mode & PHPSQLITE_NUM) {
    1859             143 :                         if (mode & PHPSQLITE_ASSOC) {
    1860              15 :                                 add_index_zval(return_value, j, decoded);
    1861              15 :                                 ZVAL_ADDREF(decoded);
    1862              15 :                                 add_assoc_zval(return_value, (char*)colnames[j], decoded);
    1863                 :                         } else {
    1864             128 :                                 add_next_index_zval(return_value, decoded);
    1865                 :                         }
    1866                 :                 } else {
    1867              54 :                         add_assoc_zval(return_value, (char*)colnames[j], decoded);
    1868                 :                 }
    1869                 :         }
    1870                 : 
    1871             147 :         if (move_next) {
    1872              85 :                 if (!res->buffered) {
    1873                 :                         /* non buffered: fetch next row */
    1874              33 :                         php_sqlite_fetch(res TSRMLS_CC);
    1875                 :                 }
    1876                 :                 /* advance the row pointer */
    1877              85 :                 res->curr_row++;
    1878                 :         }
    1879                 : }
    1880                 : /* }}} */
    1881                 : 
    1882                 : /* {{{ php_sqlite_fetch_column */
    1883                 : static void php_sqlite_fetch_column(struct php_sqlite_result *res, zval *which, zend_bool decode_binary, zval *return_value TSRMLS_DC)
    1884              38 : {
    1885                 :         int j;
    1886                 :         const char **rowdata, **colnames;
    1887                 : 
    1888                 :         /* check range of the row */
    1889              38 :         if (res->curr_row >= res->nrows) {
    1890                 :                 /* no more */
    1891               0 :                 RETURN_FALSE;
    1892                 :         }
    1893              38 :         colnames = (const char**)res->col_names;
    1894                 : 
    1895              38 :         if (Z_TYPE_P(which) == IS_LONG) {
    1896              22 :                 j = Z_LVAL_P(which);
    1897                 :         } else {
    1898              16 :                 convert_to_string_ex(&which);
    1899              24 :                 for (j = 0; j < res->ncolumns; j++) {
    1900              24 :                         if (!strcasecmp((char*)colnames[j], Z_STRVAL_P(which))) {
    1901              16 :                                 break;
    1902                 :                         }
    1903                 :                 }
    1904                 :         }
    1905              38 :         if (j < 0 || j >= res->ncolumns) {
    1906               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such column %d", j);
    1907               0 :                 RETURN_FALSE;
    1908                 :         }
    1909                 : 
    1910              38 :         if (res->buffered) {
    1911              16 :                 rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
    1912                 :         } else {
    1913              22 :                 rowdata = (const char**)res->table;
    1914                 :         }
    1915                 : 
    1916              38 :         if (rowdata[j] == NULL) {
    1917              11 :                 RETURN_NULL();
    1918              27 :         } else if (decode_binary && rowdata[j] != NULL && rowdata[j][0] == '\x01') {
    1919               0 :                 int l = strlen(rowdata[j]);
    1920               0 :                 char *decoded = emalloc(l);
    1921               0 :                 l = php_sqlite_decode_binary(rowdata[j]+1, decoded);
    1922               0 :                 decoded[l] = '\0';
    1923               0 :                 RETVAL_STRINGL(decoded, l, 0);
    1924               0 :                 if (!res->buffered) {
    1925               0 :                         efree((char*)rowdata[j]);
    1926               0 :                         rowdata[j] = NULL;
    1927                 :                 }
    1928                 :         } else {
    1929              27 :                 RETVAL_STRING((char*)rowdata[j], res->buffered);
    1930              27 :                 if (!res->buffered) {
    1931              11 :                         rowdata[j] = NULL;
    1932                 :                 }
    1933                 :         }
    1934                 : }
    1935                 : /* }}} */
    1936                 : 
    1937                 : /* {{{ proto array sqlite_fetch_all(resource result [, int result_type [, bool decode_binary]])
    1938                 :    Fetches all rows from a result set as an array of arrays. */
    1939                 : PHP_FUNCTION(sqlite_fetch_all)
    1940              10 : {
    1941                 :         zval *zres, *ent;
    1942              10 :         long mode = PHPSQLITE_BOTH;
    1943              10 :         zend_bool decode_binary = 1;
    1944                 :         struct php_sqlite_result *res;
    1945              10 :         zval *object = getThis();
    1946                 : 
    1947              10 :         if (object) {
    1948               5 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
    1949               0 :                         return;
    1950                 :                 }
    1951               5 :                 RES_FROM_OBJECT(res, object);
    1952               5 :                 if (!ZEND_NUM_ARGS()) {
    1953               5 :                         mode = res->mode;
    1954                 :                 }
    1955                 :         } else {
    1956               5 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
    1957               0 :                         return;
    1958                 :                 }
    1959               5 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    1960               5 :                 if (ZEND_NUM_ARGS() < 2) {
    1961               5 :                         mode = res->mode;
    1962                 :                 }
    1963                 :         }
    1964                 : 
    1965              10 :         if (res->curr_row >= res->nrows && res->nrows) {
    1966               4 :                 if (!res->buffered) {
    1967               2 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "One or more rowsets were already returned; returning NULL this time");
    1968                 :                 } else {
    1969               2 :                         res->curr_row = 0;
    1970                 :                 }
    1971                 :         }
    1972                 : 
    1973              10 :         array_init(return_value);
    1974                 : 
    1975              42 :         while (res->curr_row < res->nrows) {
    1976              22 :                 MAKE_STD_ZVAL(ent);
    1977              22 :                 php_sqlite_fetch_array(res, mode, decode_binary, 1, ent TSRMLS_CC);
    1978              22 :                 add_next_index_zval(return_value, ent);
    1979                 :         }
    1980                 : }
    1981                 : /* }}} */
    1982                 : 
    1983                 : /* {{{ proto array sqlite_fetch_array(resource result [, int result_type [, bool decode_binary]])
    1984                 :    Fetches the next row from a result set as an array. */
    1985                 : PHP_FUNCTION(sqlite_fetch_array)
    1986              45 : {
    1987                 :         zval *zres;
    1988              45 :         long mode = PHPSQLITE_BOTH;
    1989              45 :         zend_bool decode_binary = 1;
    1990                 :         struct php_sqlite_result *res;
    1991              45 :         zval *object = getThis();
    1992                 : 
    1993              45 :         if (object) {
    1994              15 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
    1995               0 :                         return;
    1996                 :                 }
    1997              15 :                 RES_FROM_OBJECT(res, object);
    1998              15 :                 if (!ZEND_NUM_ARGS()) {
    1999               4 :                         mode = res->mode;
    2000                 :                 }
    2001                 :         } else {
    2002              30 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
    2003               0 :                         return;
    2004                 :                 }
    2005              30 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2006              30 :                 if (ZEND_NUM_ARGS() < 2) {
    2007               4 :                         mode = res->mode;
    2008                 :                 }
    2009                 :         }
    2010                 : 
    2011              45 :         php_sqlite_fetch_array(res, mode, decode_binary, 1, return_value TSRMLS_CC);
    2012                 : }
    2013                 : /* }}} */
    2014                 : 
    2015                 : /* {{{ proto object sqlite_fetch_object(resource result [, string class_name [, NULL|array ctor_params [, bool decode_binary]]])
    2016                 :    Fetches the next row from a result set as an object. */
    2017                 :    /* note that you can do array(&$val) for param ctor_params */
    2018                 : PHP_FUNCTION(sqlite_fetch_object)
    2019              26 : {
    2020                 :         zval *zres;
    2021              26 :         zend_bool decode_binary = 1;
    2022                 :         struct php_sqlite_result *res;
    2023              26 :         zval *object = getThis();
    2024                 :         char *class_name;
    2025                 :         int class_name_len;
    2026                 :         zend_class_entry *ce;
    2027                 :         zval dataset;
    2028                 :         zend_fcall_info fci;
    2029                 :         zend_fcall_info_cache fcc;
    2030                 :         zval *retval_ptr;
    2031              26 :         zval *ctor_params = NULL;
    2032                 : 
    2033              26 :         php_set_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception TSRMLS_CC);
    2034              26 :         if (object) {
    2035              16 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szb", &class_name, &class_name_len, &ctor_params, &decode_binary)) {
    2036               0 :                         php_std_error_handling();
    2037               0 :                         return;
    2038                 :                 }
    2039              16 :                 RES_FROM_OBJECT(res, object);
    2040              16 :                 if (!ZEND_NUM_ARGS()) {
    2041               3 :                         ce = zend_standard_class_def;
    2042                 :                 } else {
    2043              13 :                         ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
    2044                 :                 }
    2045                 :         } else {
    2046              10 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|szb", &zres, &class_name, &class_name_len, &ctor_params, &decode_binary)) {
    2047               0 :                         php_std_error_handling();
    2048               0 :                         return;
    2049                 :                 }
    2050              10 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2051              10 :                 if (ZEND_NUM_ARGS() < 2) {
    2052               7 :                         ce = zend_standard_class_def;
    2053                 :                 } else {
    2054               3 :                         ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
    2055                 :                 }
    2056                 :         }
    2057                 : 
    2058              26 :         if (!ce) {
    2059               0 :                 zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Could not find class '%s'", class_name);
    2060               0 :                 php_std_error_handling();
    2061               0 :                 return;
    2062                 :         }
    2063                 : 
    2064              26 :         if (res->curr_row < res->nrows) {
    2065              21 :                 php_sqlite_fetch_array(res, PHPSQLITE_ASSOC, decode_binary, 1, &dataset TSRMLS_CC);
    2066                 :         } else {
    2067               5 :                 php_std_error_handling();
    2068               5 :                 RETURN_FALSE;
    2069                 :         }
    2070                 : 
    2071              21 :         object_and_properties_init(return_value, ce, NULL);
    2072              21 :         zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
    2073                 : 
    2074              21 :         php_std_error_handling(); /* before calling the ctor */
    2075                 : 
    2076              21 :         if (ce->constructor) {
    2077              12 :                 fci.size = sizeof(fci);
    2078              12 :                 fci.function_table = &ce->function_table;
    2079              12 :                 fci.function_name = NULL;
    2080              12 :                 fci.symbol_table = NULL;
    2081              12 :                 fci.object_pp = &return_value;
    2082              12 :                 fci.retval_ptr_ptr = &retval_ptr;
    2083              18 :                 if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
    2084               6 :                         if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
    2085               6 :                                 HashTable *ht = Z_ARRVAL_P(ctor_params);
    2086                 :                                 Bucket *p;
    2087                 : 
    2088               6 :                                 fci.param_count = 0;
    2089               6 :                                 fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
    2090               6 :                                 p = ht->pListHead;
    2091              18 :                                 while (p != NULL) {
    2092               6 :                                         fci.params[fci.param_count++] = (zval**)p->pData;
    2093               6 :                                         p = p->pListNext;
    2094                 :                                 }
    2095                 :                         } else {
    2096                 :                                 /* Two problems why we throw exceptions here: PHP is typeless
    2097                 :                                  * and hence passing one argument that's not an array could be
    2098                 :                                  * by mistake and the other way round is possible, too. The
    2099                 :                                  * single value is an array. Also we'd have to make that one
    2100                 :                                  * argument passed by reference.
    2101                 :                                  */
    2102               0 :                                 zend_throw_exception(sqlite_ce_exception, "Parameter ctor_params must be an array", 0 TSRMLS_CC);
    2103               0 :                                 return;
    2104                 :                         }
    2105                 :                 } else {
    2106               6 :                         fci.param_count = 0;
    2107               6 :                         fci.params = NULL;
    2108                 :                 }
    2109              12 :                 fci.no_separation = 1;
    2110                 : 
    2111              12 :                 fcc.initialized = 1;
    2112              12 :                 fcc.function_handler = ce->constructor;
    2113              12 :                 fcc.calling_scope = EG(scope);
    2114              12 :                 fcc.object_pp = &return_value;
    2115                 : 
    2116              12 :                 if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
    2117               0 :                         zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Could not execute %s::%s()", class_name, ce->constructor->common.function_name);
    2118                 :                 } else {
    2119              12 :                         if (retval_ptr) {
    2120              12 :                                 zval_ptr_dtor(&retval_ptr);
    2121                 :                         }
    2122                 :                 }
    2123              12 :                 if (fci.params) {
    2124               6 :                         efree(fci.params);
    2125                 :                 }
    2126               9 :         } else if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
    2127               0 :                 zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Class %s does not have a constructor, use NULL for parameter ctor_params or omit it", class_name);
    2128                 :         }
    2129                 : }
    2130                 : /* }}} */
    2131                 : 
    2132                 : /* {{{ proto array sqlite_array_query(resource db, string query [ , int result_type [, bool decode_binary]])
    2133                 :    Executes a query against a given database and returns an array of arrays. */
    2134                 : PHP_FUNCTION(sqlite_array_query)
    2135               6 : {
    2136                 :         zval *zdb, *ent;
    2137                 :         struct php_sqlite_db *db;
    2138                 :         struct php_sqlite_result *rres;
    2139                 :         char *sql;
    2140                 :         int sql_len;
    2141               6 :         long mode = PHPSQLITE_BOTH;
    2142               6 :         char *errtext = NULL;
    2143               6 :         zend_bool decode_binary = 1;
    2144               6 :         zval *object = getThis();
    2145                 : 
    2146               6 :         if (object) {
    2147               3 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &sql, &sql_len, &mode, &decode_binary)) {
    2148               1 :                         return;
    2149                 :                 }
    2150               2 :                 DB_FROM_OBJECT(db, object);
    2151                 :         } else {
    2152               3 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    2153                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|lb", &sql, &sql_len, &zdb, &mode, &decode_binary) &&
    2154                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zdb, &sql, &sql_len, &mode, &decode_binary)) {
    2155               0 :                         return;
    2156                 :                 }
    2157               3 :                 DB_FROM_ZVAL(db, &zdb);
    2158                 :         }
    2159                 : 
    2160               5 :         PHP_SQLITE_EMPTY_QUERY;
    2161                 : 
    2162                 :         /* avoid doing work if we can */
    2163               3 :         if (!return_value_used) {
    2164               1 :                 db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    2165                 : 
    2166               1 :                 if (db->last_err_code != SQLITE_OK) {
    2167               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    2168               1 :                         sqlite_freemem(errtext);
    2169                 :                 }
    2170               1 :                 return;
    2171                 :         }
    2172                 : 
    2173               2 :         rres = (struct php_sqlite_result *)emalloc(sizeof(*rres));
    2174               2 :         sqlite_query(NULL, db, sql, sql_len, (int)mode, 0, NULL, &rres, NULL TSRMLS_CC);
    2175               2 :         if (db->last_err_code != SQLITE_OK) {
    2176               0 :                 if (rres) {
    2177               0 :                         efree(rres);
    2178                 :                 }
    2179               0 :                 RETURN_FALSE;
    2180                 :         }
    2181                 : 
    2182               2 :         array_init(return_value);
    2183                 : 
    2184              10 :         while (rres->curr_row < rres->nrows) {
    2185               6 :                 MAKE_STD_ZVAL(ent);
    2186               6 :                 php_sqlite_fetch_array(rres, mode, decode_binary, 1, ent TSRMLS_CC);
    2187               6 :                 add_next_index_zval(return_value, ent);
    2188                 :         }
    2189               2 :         real_result_dtor(rres TSRMLS_CC);
    2190                 : }
    2191                 : /* }}} */
    2192                 : 
    2193                 : /* {{{ php_sqlite_fetch_single */
    2194                 : static void php_sqlite_fetch_single(struct php_sqlite_result *res, zend_bool decode_binary, zval *return_value TSRMLS_DC)
    2195              35 : {
    2196                 :         const char **rowdata;
    2197                 :         char *decoded;
    2198                 :         int decoded_len;
    2199                 : 
    2200                 :         /* check range of the row */
    2201              35 :         if (res->curr_row >= res->nrows) {
    2202                 :                 /* no more */
    2203               0 :                 RETURN_FALSE;
    2204                 :         }
    2205                 : 
    2206              35 :         if (res->buffered) {
    2207               4 :                 rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
    2208                 :         } else {
    2209              31 :                 rowdata = (const char**)res->table;
    2210                 :         }
    2211                 : 
    2212              35 :         if (decode_binary && rowdata[0] != NULL && rowdata[0][0] == '\x01') {
    2213               0 :                 decoded = emalloc(strlen(rowdata[0]));
    2214               0 :                 decoded_len = php_sqlite_decode_binary(rowdata[0]+1, decoded);
    2215               0 :                 if (!res->buffered) {
    2216               0 :                         efree((char*)rowdata[0]);
    2217               0 :                         rowdata[0] = NULL;
    2218                 :                 }
    2219              35 :         } else if (rowdata[0]) {
    2220              33 :                 decoded_len = strlen((char*)rowdata[0]);
    2221              33 :                 if (res->buffered) {
    2222               4 :                         decoded = estrndup((char*)rowdata[0], decoded_len);
    2223                 :                 } else {
    2224              29 :                         decoded = (char*)rowdata[0];
    2225              29 :                         rowdata[0] = NULL;
    2226                 :                 }
    2227                 :         } else {
    2228               2 :                 decoded = NULL;
    2229               2 :                 decoded_len = 0;
    2230                 :         }
    2231                 : 
    2232              35 :         if (!res->buffered) {
    2233                 :                 /* non buffered: fetch next row */
    2234              31 :                 php_sqlite_fetch(res TSRMLS_CC);
    2235                 :         }
    2236                 :         /* advance the row pointer */
    2237              35 :         res->curr_row++;
    2238                 : 
    2239              35 :         if (decoded == NULL) {
    2240               2 :                 RETURN_NULL();
    2241                 :         } else {
    2242              33 :                 RETURN_STRINGL(decoded, decoded_len, 0);
    2243                 :         }
    2244                 : }
    2245                 : /* }}} */
    2246                 : 
    2247                 : 
    2248                 : /* {{{ proto array sqlite_single_query(resource db, string query [, bool first_row_only [, bool decode_binary]])
    2249                 :    Executes a query and returns either an array for one single column or the value of the first row. */
    2250                 : PHP_FUNCTION(sqlite_single_query)
    2251              26 : {
    2252                 :         zval *zdb, *ent;
    2253                 :         struct php_sqlite_db *db;
    2254                 :         struct php_sqlite_result *rres;
    2255                 :         char *sql;
    2256                 :         int sql_len;
    2257              26 :         char *errtext = NULL;
    2258              26 :         zend_bool decode_binary = 1;
    2259              26 :         zend_bool srow = 1;
    2260              26 :         zval *object = getThis();
    2261                 : 
    2262              26 :         if (object) {
    2263              19 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb", &sql, &sql_len, &srow, &decode_binary)) {
    2264               0 :                         return;
    2265                 :                 }
    2266              19 :                 RES_FROM_OBJECT(db, object);
    2267                 :         } else {
    2268               7 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    2269                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|bb", &sql, &sql_len, &zdb, &srow, &decode_binary) &&
    2270                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|bb", &zdb, &sql, &sql_len, &srow, &decode_binary)) {
    2271               0 :                         return;
    2272                 :                 }
    2273               7 :                 DB_FROM_ZVAL(db, &zdb);
    2274                 :         }
    2275                 : 
    2276              26 :         PHP_SQLITE_EMPTY_QUERY;
    2277                 : 
    2278                 :         /* avoid doing work if we can */
    2279              26 :         if (!return_value_used) {
    2280               0 :                 db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    2281                 : 
    2282               0 :                 if (db->last_err_code != SQLITE_OK) {
    2283               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    2284               0 :                         sqlite_freemem(errtext);
    2285                 :                 }
    2286               0 :                 return;
    2287                 :         }
    2288                 : 
    2289              26 :         rres = (struct php_sqlite_result *)emalloc(sizeof(*rres));
    2290              26 :         sqlite_query(NULL, db, sql, sql_len, PHPSQLITE_NUM, 0, NULL, &rres, NULL TSRMLS_CC);
    2291              26 :         if (db->last_err_code != SQLITE_OK) {
    2292               3 :                 if (rres) {
    2293               2 :                         efree(rres);
    2294                 :                 }
    2295               3 :                 RETURN_FALSE;
    2296                 :         }
    2297                 : 
    2298              23 :         if (!srow) {
    2299               2 :                 array_init(return_value);
    2300                 :         }
    2301                 : 
    2302              56 :         while (rres->curr_row < rres->nrows) {
    2303              27 :                 MAKE_STD_ZVAL(ent);
    2304              27 :                 php_sqlite_fetch_single(rres, decode_binary, ent TSRMLS_CC);
    2305                 : 
    2306                 :                 /* if set and we only have 1 row in the result set, return the result as a string. */
    2307              27 :                 if (srow) {
    2308              19 :                         if (rres->curr_row == 1 && rres->curr_row >= rres->nrows) {
    2309              17 :                                 *return_value = *ent;
    2310              17 :                                 zval_copy_ctor(return_value);
    2311              17 :                                 zval_dtor(ent);
    2312              17 :                                 FREE_ZVAL(ent);
    2313              17 :                                 break;
    2314                 :                         } else {
    2315               2 :                                 srow = 0;
    2316               2 :                                 array_init(return_value);
    2317                 :                         }
    2318                 :                 }
    2319              10 :                 add_next_index_zval(return_value, ent);
    2320                 :         }
    2321                 : 
    2322              23 :         real_result_dtor(rres TSRMLS_CC);
    2323                 : }
    2324                 : /* }}} */
    2325                 : 
    2326                 : 
    2327                 : /* {{{ proto string sqlite_fetch_single(resource result [, bool decode_binary])
    2328                 :    Fetches the first column of a result set as a string. */
    2329                 : PHP_FUNCTION(sqlite_fetch_single)
    2330               8 : {
    2331                 :         zval *zres;
    2332               8 :         zend_bool decode_binary = 1;
    2333                 :         struct php_sqlite_result *res;
    2334               8 :         zval *object = getThis();
    2335                 : 
    2336               8 :         if (object) {
    2337               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &decode_binary)) {
    2338               0 :                         return;
    2339                 :                 }
    2340               4 :                 RES_FROM_OBJECT(res, object);
    2341                 :         } else {
    2342               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zres, &decode_binary)) {
    2343               0 :                         return;
    2344                 :                 }
    2345               4 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2346                 :         }
    2347                 : 
    2348               8 :         php_sqlite_fetch_single(res, decode_binary, return_value TSRMLS_CC);
    2349                 : }
    2350                 : /* }}} */
    2351                 : 
    2352                 : /* {{{ proto array sqlite_current(resource result [, int result_type [, bool decode_binary]])
    2353                 :    Fetches the current row from a result set as an array. */
    2354                 : PHP_FUNCTION(sqlite_current)
    2355              48 : {
    2356                 :         zval *zres;
    2357              48 :         long mode = PHPSQLITE_BOTH;
    2358              48 :         zend_bool decode_binary = 1;
    2359                 :         struct php_sqlite_result *res;
    2360              48 :         zval *object = getThis();
    2361                 : 
    2362              48 :         if (object) {
    2363              17 :                 if (ZEND_NUM_ARGS() && FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
    2364               0 :                         return;
    2365                 :                 }
    2366              17 :                 RES_FROM_OBJECT(res, object);
    2367              17 :                 if (!ZEND_NUM_ARGS()) {
    2368              13 :                         mode = res->mode;
    2369                 :                 }
    2370                 :         } else {
    2371              31 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
    2372               0 :                         return;
    2373                 :                 }
    2374              31 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2375              31 :                 if (ZEND_NUM_ARGS() < 2) {
    2376              20 :                         mode = res->mode;
    2377                 :                 }
    2378                 :         }
    2379                 : 
    2380              48 :         php_sqlite_fetch_array(res, mode, decode_binary, 0, return_value TSRMLS_CC);
    2381                 : }
    2382                 : /* }}} */
    2383                 : 
    2384                 : /* {{{ proto mixed sqlite_column(resource result, mixed index_or_name [, bool decode_binary])
    2385                 :    Fetches a column from the current row of a result set. */
    2386                 : PHP_FUNCTION(sqlite_column)
    2387              38 : {
    2388                 :         zval *zres;
    2389                 :         zval *which;
    2390              38 :         zend_bool decode_binary = 1;
    2391                 :         struct php_sqlite_result *res;
    2392              38 :         zval *object = getThis();
    2393                 : 
    2394              38 :         if (object) {
    2395              22 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &which, &decode_binary)) {
    2396               0 :                         return;
    2397                 :                 }
    2398              22 :                 RES_FROM_OBJECT(res, object);
    2399                 :         } else {
    2400              16 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zres, &which, &decode_binary)) {
    2401               0 :                         return;
    2402                 :                 }
    2403              16 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2404                 :         }
    2405                 : 
    2406              38 :         php_sqlite_fetch_column(res, which, decode_binary, return_value TSRMLS_CC);
    2407                 : }
    2408                 : /* }}} */
    2409                 : 
    2410                 : /* {{{ proto string sqlite_libversion()
    2411                 :    Returns the version of the linked SQLite library. */
    2412                 : PHP_FUNCTION(sqlite_libversion)
    2413               0 : {
    2414               0 :         if (ZEND_NUM_ARGS() != 0) {
    2415               0 :                 WRONG_PARAM_COUNT;
    2416                 :         }
    2417               0 :         RETURN_STRING((char*)sqlite_libversion(), 1);
    2418                 : }
    2419                 : /* }}} */
    2420                 : 
    2421                 : /* {{{ proto string sqlite_libencoding()
    2422                 :    Returns the encoding (iso8859 or UTF-8) of the linked SQLite library. */
    2423                 : PHP_FUNCTION(sqlite_libencoding)
    2424               0 : {
    2425               0 :         if (ZEND_NUM_ARGS() != 0) {
    2426               0 :                 WRONG_PARAM_COUNT;
    2427                 :         }
    2428               0 :         RETURN_STRING((char*)sqlite_libencoding(), 1);
    2429                 : }
    2430                 : /* }}} */
    2431                 : 
    2432                 : /* {{{ proto int sqlite_changes(resource db)
    2433                 :    Returns the number of rows that were changed by the most recent SQL statement. */
    2434                 : PHP_FUNCTION(sqlite_changes)
    2435               6 : {
    2436                 :         zval *zdb;
    2437                 :         struct php_sqlite_db *db;
    2438               6 :         zval *object = getThis();
    2439                 : 
    2440               6 :         if (object) {
    2441               6 :                 if (ZEND_NUM_ARGS() != 0) {
    2442               0 :                         WRONG_PARAM_COUNT
    2443                 :                 }
    2444               6 :                 DB_FROM_OBJECT(db, object);
    2445                 :         } else {
    2446               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
    2447               0 :                         return;
    2448                 :                 }
    2449               0 :                 DB_FROM_ZVAL(db, &zdb);
    2450                 :         }
    2451                 : 
    2452               6 :         RETURN_LONG(sqlite_changes(db->db));
    2453                 : }
    2454                 : /* }}} */
    2455                 : 
    2456                 : /* {{{ proto int sqlite_last_insert_rowid(resource db)
    2457                 :    Returns the rowid of the most recently inserted row. */
    2458                 : PHP_FUNCTION(sqlite_last_insert_rowid)
    2459               0 : {
    2460                 :         zval *zdb;
    2461                 :         struct php_sqlite_db *db;
    2462               0 :         zval *object = getThis();
    2463                 : 
    2464               0 :         if (object) {
    2465               0 :                 if (ZEND_NUM_ARGS() != 0) {
    2466               0 :                         WRONG_PARAM_COUNT
    2467                 :                 }
    2468               0 :                 DB_FROM_OBJECT(db, object);
    2469                 :         } else {
    2470               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
    2471               0 :                         return;
    2472                 :                 }
    2473               0 :                 DB_FROM_ZVAL(db, &zdb);
    2474                 :         }
    2475                 : 
    2476               0 :         RETURN_LONG(sqlite_last_insert_rowid(db->db));
    2477                 : }
    2478                 : /* }}} */
    2479                 : 
    2480                 : static int sqlite_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
    2481               1 : {
    2482               1 :         sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC);
    2483                 : 
    2484               1 :         if (obj->u.res == NULL) {
    2485               1 :                 zend_throw_exception(sqlite_ce_exception, "Row count is not available for this query", 0 TSRMLS_CC);
    2486               1 :                 return FAILURE;
    2487                 :         }
    2488                 : 
    2489               0 :         if (obj->u.res->buffered) {
    2490               0 :                 * count = obj->u.res->nrows;
    2491               0 :                 return SUCCESS;
    2492                 :         } else {
    2493               0 :                 zend_throw_exception(sqlite_ce_exception, "Row count is not available for unbuffered queries", 0 TSRMLS_CC);
    2494               0 :                 return FAILURE;
    2495                 :         }
    2496                 : } /* }}} */
    2497                 : 
    2498                 : /* {{{ proto int sqlite_num_rows(resource result)
    2499                 :    Returns the number of rows in a buffered result set. */
    2500                 : PHP_FUNCTION(sqlite_num_rows)
    2501               2 : {
    2502                 :         zval *zres;
    2503                 :         struct php_sqlite_result *res;
    2504               2 :         zval *object = getThis();
    2505                 : 
    2506               2 :         if (object) {
    2507               2 :                 if (ZEND_NUM_ARGS() != 0) {
    2508               0 :                         WRONG_PARAM_COUNT
    2509                 :                 }
    2510               2 :                 RES_FROM_OBJECT(res, object);
    2511                 :         } else {
    2512               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2513               0 :                         return;
    2514                 :                 }
    2515               0 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2516                 :         }
    2517                 : 
    2518               2 :         if (res->buffered) {
    2519               2 :                 RETURN_LONG(res->nrows);
    2520                 :         } else {
    2521               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Row count is not available for unbuffered queries");
    2522               0 :                 RETURN_FALSE;
    2523                 :         }
    2524                 : }
    2525                 : /* }}} */
    2526                 : 
    2527                 : /* {{{ proto bool sqlite_valid(resource result)
    2528                 :    Returns whether more rows are available. */
    2529                 : PHP_FUNCTION(sqlite_valid)
    2530              71 : {
    2531                 :         zval *zres;
    2532                 :         struct php_sqlite_result *res;
    2533              71 :         zval *object = getThis();
    2534                 : 
    2535              71 :         if (object) {
    2536              31 :                 if (ZEND_NUM_ARGS() != 0) {
    2537               0 :                         WRONG_PARAM_COUNT
    2538                 :                 }
    2539              31 :                 RES_FROM_OBJECT(res, object);
    2540                 :         } else {
    2541              40 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2542               0 :                         return;
    2543                 :                 }
    2544              40 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2545                 :         }
    2546                 : 
    2547              71 :         RETURN_BOOL(res->curr_row < res->nrows && res->nrows); /* curr_row may be -1 */
    2548                 : }
    2549                 : /* }}} */
    2550                 : 
    2551                 : /* {{{ proto bool sqlite_has_prev(resource result)
    2552                 :  * Returns whether a previous row is available. */
    2553                 : PHP_FUNCTION(sqlite_has_prev)
    2554               4 : {
    2555                 :         zval *zres;
    2556                 :         struct php_sqlite_result *res;
    2557               4 :         zval *object = getThis();
    2558                 : 
    2559               4 :         if (object) {
    2560               0 :                 if (ZEND_NUM_ARGS() != 0) {
    2561               0 :                         WRONG_PARAM_COUNT
    2562                 :                 }
    2563               0 :                 RES_FROM_OBJECT(res, object);
    2564                 :         } else {
    2565               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2566               0 :                         return;
    2567                 :                 }
    2568               4 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2569                 :         }
    2570                 : 
    2571               4 :         if(!res->buffered) {
    2572               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "you cannot use sqlite_has_prev on unbuffered querys");
    2573               1 :                 RETURN_FALSE;
    2574                 :         }
    2575                 : 
    2576               3 :         RETURN_BOOL(res->curr_row);
    2577                 : }
    2578                 : /* }}} */
    2579                 : 
    2580                 : /* {{{ proto int sqlite_num_fields(resource result)
    2581                 :    Returns the number of fields in a result set. */
    2582                 : PHP_FUNCTION(sqlite_num_fields)
    2583              16 : {
    2584                 :         zval *zres;
    2585                 :         struct php_sqlite_result *res;
    2586              16 :         zval *object = getThis();
    2587                 : 
    2588              16 :         if (object) {
    2589               8 :                 if (ZEND_NUM_ARGS() != 0) {
    2590               0 :                         WRONG_PARAM_COUNT
    2591                 :                 }
    2592               8 :                 RES_FROM_OBJECT(res, object);
    2593                 :         } else {
    2594               8 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2595               0 :                         return;
    2596                 :                 }
    2597               8 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2598                 :         }
    2599                 : 
    2600              16 :         RETURN_LONG(res->ncolumns);
    2601                 : }
    2602                 : /* }}} */
    2603                 : 
    2604                 : /* {{{ proto string sqlite_field_name(resource result, int field_index)
    2605                 :    Returns the name of a particular field of a result set. */
    2606                 : PHP_FUNCTION(sqlite_field_name)
    2607              12 : {
    2608                 :         zval *zres;
    2609                 :         struct php_sqlite_result *res;
    2610                 :         long field;
    2611              12 :         zval *object = getThis();
    2612                 : 
    2613              12 :         if (object) {
    2614               6 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &field)) {
    2615               0 :                         return;
    2616                 :                 }
    2617               6 :                 RES_FROM_OBJECT(res, object);
    2618                 :         } else {
    2619               6 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &field)) {
    2620               0 :                         return;
    2621                 :                 }
    2622               6 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2623                 :         }
    2624                 : 
    2625              12 :         if (field < 0 || field >= res->ncolumns) {
    2626               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %ld out of range", field);
    2627               0 :                 RETURN_FALSE;
    2628                 :         }
    2629                 : 
    2630              12 :         RETURN_STRING(res->col_names[field], 1);
    2631                 : }
    2632                 : /* }}} */
    2633                 : 
    2634                 : /* {{{ proto bool sqlite_seek(resource result, int row)
    2635                 :    Seek to a particular row number of a buffered result set. */
    2636                 : PHP_FUNCTION(sqlite_seek)
    2637              20 : {
    2638                 :         zval *zres;
    2639                 :         struct php_sqlite_result *res;
    2640                 :         long row;
    2641              20 :         zval *object = getThis();
    2642                 : 
    2643              20 :         if (object) {
    2644              10 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &row)) {
    2645               0 :                         return;
    2646                 :                 }
    2647              10 :                 RES_FROM_OBJECT(res, object);
    2648                 :         } else {
    2649              10 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &row)) {
    2650               0 :                         return;
    2651                 :                 }
    2652              10 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2653                 :         }
    2654                 : 
    2655              20 :         if (!res->buffered) {
    2656               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set");
    2657               0 :                 RETURN_FALSE;
    2658                 :         }
    2659                 : 
    2660              20 :         if (row < 0 || row >= res->nrows) {
    2661               8 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "row %ld out of range", row);
    2662               8 :                 RETURN_FALSE;
    2663                 :         }
    2664                 : 
    2665              12 :         res->curr_row = row;
    2666              12 :         RETURN_TRUE;
    2667                 : }
    2668                 : /* }}} */
    2669                 : 
    2670                 : /* {{{ proto bool sqlite_rewind(resource result)
    2671                 :    Seek to the first row number of a buffered result set. */
    2672                 : PHP_FUNCTION(sqlite_rewind)
    2673               3 : {
    2674                 :         zval *zres;
    2675                 :         struct php_sqlite_result *res;
    2676               3 :         zval *object = getThis();
    2677                 : 
    2678               3 :         if (object) {
    2679               0 :                 if (ZEND_NUM_ARGS() != 0) {
    2680               0 :                         WRONG_PARAM_COUNT
    2681                 :                 }
    2682               0 :                 RES_FROM_OBJECT(res, object);
    2683                 :         } else {
    2684               3 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2685               0 :                         return;
    2686                 :                 }
    2687               3 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2688                 :         }
    2689                 : 
    2690               3 :         if (!res->buffered) {
    2691               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot rewind an unbuffered result set");
    2692               1 :                 RETURN_FALSE;
    2693                 :         }
    2694                 : 
    2695               2 :         if (!res->nrows) {
    2696               0 :                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "no rows received");
    2697               0 :                 RETURN_FALSE;
    2698                 :         }
    2699                 : 
    2700               2 :         res->curr_row = 0;
    2701               2 :         RETURN_TRUE;
    2702                 : }
    2703                 : /* }}} */
    2704                 : 
    2705                 : /* {{{ proto bool sqlite_next(resource result)
    2706                 :    Seek to the next row number of a result set. */
    2707                 : PHP_FUNCTION(sqlite_next)
    2708              31 : {
    2709                 :         zval *zres;
    2710                 :         struct php_sqlite_result *res;
    2711              31 :         zval *object = getThis();
    2712                 : 
    2713              31 :         if (object) {
    2714              12 :                 if (ZEND_NUM_ARGS() != 0) {
    2715               0 :                         WRONG_PARAM_COUNT
    2716                 :                 }
    2717              12 :                 RES_FROM_OBJECT(res, object);
    2718                 :         } else {
    2719              19 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2720               0 :                         return;
    2721                 :                 }
    2722              19 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2723                 :         }
    2724                 : 
    2725              31 :         if (!res->buffered && res->vm) {
    2726              18 :                 php_sqlite_fetch(res TSRMLS_CC);
    2727                 :         }
    2728                 : 
    2729              31 :         if (res->curr_row >= res->nrows) {
    2730               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no more rows available");
    2731               0 :                 RETURN_FALSE;
    2732                 :         }
    2733                 : 
    2734              31 :         res->curr_row++;
    2735                 : 
    2736              31 :         RETURN_TRUE;
    2737                 : }
    2738                 : /* }}} */
    2739                 : 
    2740                 : /* {{{ proto int sqlite_key(resource result)
    2741                 :    Return the current row index of a buffered result. */
    2742                 : PHP_FUNCTION(sqlite_key)
    2743               0 : {
    2744                 :         zval *zres;
    2745                 :         struct php_sqlite_result *res;
    2746               0 :         zval *object = getThis();
    2747                 : 
    2748               0 :         if (object) {
    2749               0 :                 if (ZEND_NUM_ARGS() != 0) {
    2750               0 :                         WRONG_PARAM_COUNT
    2751                 :                 }
    2752               0 :                 RES_FROM_OBJECT(res, object);
    2753                 :         } else {
    2754               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2755               0 :                         return;
    2756                 :                 }
    2757               0 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2758                 :         }
    2759                 : 
    2760               0 :         RETURN_LONG(res->curr_row);
    2761                 : }
    2762                 : /* }}} */
    2763                 : 
    2764                 : /* {{{ proto bool sqlite_prev(resource result)
    2765                 :  * Seek to the previous row number of a result set. */
    2766                 : PHP_FUNCTION(sqlite_prev)
    2767               4 : {
    2768                 :         zval *zres;
    2769                 :         struct php_sqlite_result *res;
    2770               4 :         zval *object = getThis();
    2771                 : 
    2772               4 :         if (object) {
    2773               0 :                 if (ZEND_NUM_ARGS() != 0) {
    2774               0 :                         WRONG_PARAM_COUNT
    2775                 :                 }
    2776               0 :                 RES_FROM_OBJECT(res, object);
    2777                 :         } else {
    2778               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2779               0 :                         return;
    2780                 :                 }
    2781               4 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2782                 :         }
    2783                 : 
    2784               4 :         if (!res->buffered) {
    2785               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "you cannot use sqlite_prev on unbuffered querys");
    2786               1 :                 RETURN_FALSE;
    2787                 :         }
    2788                 : 
    2789               3 :         if (res->curr_row <= 0) {
    2790               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no previous row available");
    2791               0 :                 RETURN_FALSE;
    2792                 :         }
    2793                 : 
    2794               3 :         res->curr_row--;
    2795                 : 
    2796               3 :         RETURN_TRUE;
    2797                 : }
    2798                 : /* }}} */
    2799                 : 
    2800                 : /* {{{ proto string sqlite_escape_string(string item)
    2801                 :    Escapes a string for use as a query parameter. */
    2802                 : PHP_FUNCTION(sqlite_escape_string)
    2803              15 : {
    2804              15 :         char *string = NULL;
    2805                 :         int stringlen;
    2806                 :         char *ret;
    2807                 : 
    2808              15 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &stringlen)) {
    2809               0 :                 return;
    2810                 :         }
    2811                 : 
    2812              18 :         if (stringlen && (string[0] == '\x01' || memchr(string, '\0', stringlen) != NULL)) {
    2813                 :                 /* binary string */
    2814                 :                 int enclen;
    2815                 : 
    2816               3 :                 ret = safe_emalloc(1 + stringlen / 254, 257, 3);
    2817               3 :                 ret[0] = '\x01';
    2818               3 :                 enclen = php_sqlite_encode_binary(string, stringlen, ret+1);
    2819               3 :                 RETVAL_STRINGL(ret, enclen+1, 0);
    2820                 : 
    2821              12 :         } else if (stringlen) {
    2822              11 :                 ret = sqlite_mprintf("%q", string);
    2823              11 :                 if (ret) {
    2824              11 :                         RETVAL_STRING(ret, 1);
    2825              11 :                         sqlite_freemem(ret);
    2826                 :                 }
    2827                 :         } else {
    2828               1 :                 RETURN_EMPTY_STRING();
    2829                 :         }
    2830                 : }
    2831                 : /* }}} */
    2832                 : 
    2833                 : /* {{{ proto int sqlite_last_error(resource db)
    2834                 :    Returns the error code of the last error for a database. */
    2835                 : PHP_FUNCTION(sqlite_last_error)
    2836               0 : {
    2837                 :         zval *zdb;
    2838                 :         struct php_sqlite_db *db;
    2839               0 :         zval *object = getThis();
    2840                 : 
    2841               0 :         if (object) {
    2842               0 :                 if (ZEND_NUM_ARGS() != 0) {
    2843               0 :                         WRONG_PARAM_COUNT
    2844                 :                 }
    2845               0 :                 DB_FROM_OBJECT(db, object);
    2846                 :         } else {
    2847               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
    2848               0 :                         return;
    2849                 :                 }
    2850               0 :                 DB_FROM_ZVAL(db, &zdb);
    2851                 :         }
    2852                 : 
    2853               0 :         RETURN_LONG(db->last_err_code);
    2854                 : }
    2855                 : /* }}} */
    2856                 : 
    2857                 : /* {{{ proto string sqlite_error_string(int error_code)
    2858                 :    Returns the textual description of an error code. */
    2859                 : PHP_FUNCTION(sqlite_error_string)
    2860               0 : {
    2861                 :         long code;
    2862                 :         const char *msg;
    2863                 : 
    2864               0 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
    2865               0 :                 return;
    2866                 :         }
    2867                 : 
    2868               0 :         msg = sqlite_error_string(code);
    2869                 : 
    2870               0 :         if (msg) {
    2871               0 :                 RETURN_STRING((char*)msg, 1);
    2872                 :         } else {
    2873               0 :                 RETURN_NULL();
    2874                 :         }
    2875                 : }
    2876                 : /* }}} */
    2877                 : 
    2878                 : /* manages duplicate registrations of a particular function, and
    2879                 :  * also handles the case where the db is using a persistent connection */
    2880                 : enum callback_prep_t { DO_REG, SKIP_REG, ERR };
    2881                 : 
    2882                 : static enum callback_prep_t prep_callback_struct(struct php_sqlite_db *db, int is_agg,
    2883                 :                 char *funcname,
    2884                 :                 zval *step, zval *fini, struct php_sqlite_agg_functions **funcs)
    2885               3 : {
    2886                 :         struct php_sqlite_agg_functions *alloc_funcs, func_tmp;
    2887                 :         char *hashkey;
    2888                 :         int hashkeylen;
    2889                 :         enum callback_prep_t ret;
    2890                 : 
    2891               3 :         hashkeylen = spprintf(&hashkey, 0, "%s-%s", is_agg ? "agg" : "reg", funcname);
    2892                 : 
    2893                 :         /* is it already registered ? */
    2894               3 :         if (SUCCESS == zend_hash_find(&db->callbacks, hashkey, hashkeylen+1, (void*)&alloc_funcs)) {
    2895                 :                 /* override the previous definition */
    2896                 : 
    2897               0 :                 if (alloc_funcs->is_valid) {
    2898                 :                         /* release these */
    2899                 : 
    2900               0 :                         if (alloc_funcs->step) {
    2901               0 :                                 zval_ptr_dtor(&alloc_funcs->step);
    2902               0 :                                 alloc_funcs->step = NULL;
    2903                 :                         }
    2904                 : 
    2905               0 :                         if (alloc_funcs->fini) {
    2906               0 :                                 zval_ptr_dtor(&alloc_funcs->fini);
    2907               0 :                                 alloc_funcs->fini = NULL;
    2908                 :                         }
    2909                 :                 }
    2910                 : 
    2911               0 :                 ret = SKIP_REG;
    2912                 :         } else {
    2913                 :                 /* add a new one */
    2914               3 :                 func_tmp.db = db;
    2915                 : 
    2916               3 :                 ret = SUCCESS == zend_hash_update(&db->callbacks, hashkey, hashkeylen+1,
    2917                 :                                 (void*)&func_tmp, sizeof(func_tmp), (void**)&alloc_funcs) ? DO_REG : ERR;
    2918                 :         }
    2919                 : 
    2920               3 :         efree(hashkey);
    2921                 : 
    2922               3 :         MAKE_STD_ZVAL(alloc_funcs->step);
    2923               3 :         *(alloc_funcs->step)  = *step;
    2924               3 :         zval_copy_ctor(alloc_funcs->step);
    2925               3 :         INIT_PZVAL(alloc_funcs->step);
    2926                 : 
    2927               3 :         if (is_agg) {
    2928               1 :                 MAKE_STD_ZVAL(alloc_funcs->fini);
    2929               1 :                 *(alloc_funcs->fini) = *fini;
    2930               1 :                 zval_copy_ctor(alloc_funcs->fini);
    2931               1 :                 INIT_PZVAL(alloc_funcs->fini);
    2932                 :         } else {
    2933               2 :                 alloc_funcs->fini = NULL;
    2934                 :         }
    2935               3 :         alloc_funcs->is_valid = 1;
    2936               3 :         *funcs = alloc_funcs;
    2937                 : 
    2938               3 :         return ret;
    2939                 : }
    2940                 : 
    2941                 : 
    2942                 : /* {{{ proto bool sqlite_create_aggregate(resource db, string funcname, mixed step_func, mixed finalize_func[, long num_args])
    2943                 :     Registers an aggregate function for queries. */
    2944                 : PHP_FUNCTION(sqlite_create_aggregate)
    2945               1 : {
    2946               1 :         char *funcname = NULL;
    2947                 :         int funcname_len;
    2948                 :         zval *zstep, *zfinal, *zdb;
    2949                 :         struct php_sqlite_db *db;
    2950                 :         struct php_sqlite_agg_functions *funcs;
    2951               1 :         char *callable = NULL;
    2952               1 :         long num_args = -1;
    2953               1 :         zval *object = getThis();
    2954                 : 
    2955               1 :         if (object) {
    2956               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
    2957               0 :                         return;
    2958                 :                 }
    2959               0 :                 DB_FROM_OBJECT(db, object);
    2960                 :         } else {
    2961               1 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rszz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
    2962               0 :                         return;
    2963                 :                 }
    2964               1 :                 DB_FROM_ZVAL(db, &zdb);
    2965                 :         }
    2966                 : 
    2967               1 :         if (!zend_is_callable(zstep, 0, &callable)) {
    2968               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "step function `%s' is not callable", callable);
    2969               0 :                 efree(callable);
    2970               0 :                 return;
    2971                 :         }
    2972               1 :         efree(callable);
    2973                 : 
    2974               1 :         if (!zend_is_callable(zfinal, 0, &callable)) {
    2975               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "finalize function `%s' is not callable", callable);
    2976               0 :                 efree(callable);
    2977               0 :                 return;
    2978                 :         }
    2979               1 :         efree(callable);
    2980                 : 
    2981                 : 
    2982               1 :         if (prep_callback_struct(db, 1, funcname, zstep, zfinal, &funcs) == DO_REG) {
    2983               1 :                 sqlite_create_aggregate(db->db, funcname, num_args,
    2984                 :                                 php_sqlite_agg_step_function_callback,
    2985                 :                                 php_sqlite_agg_fini_function_callback, funcs);
    2986                 :         }
    2987                 : 
    2988                 : 
    2989                 : }
    2990                 : /* }}} */
    2991                 : 
    2992                 : /* {{{ proto bool sqlite_create_function(resource db, string funcname, mixed callback[, long num_args])
    2993                 :     Registers a "regular" function for queries. */
    2994                 : PHP_FUNCTION(sqlite_create_function)
    2995               2 : {
    2996               2 :         char *funcname = NULL;
    2997                 :         int funcname_len;
    2998                 :         zval *zcall, *zdb;
    2999                 :         struct php_sqlite_db *db;
    3000                 :         struct php_sqlite_agg_functions *funcs;
    3001               2 :         char *callable = NULL;
    3002               2 :         long num_args = -1;
    3003                 : 
    3004               2 :         zval *object = getThis();
    3005                 : 
    3006               2 :         if (object) {
    3007               1 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &funcname, &funcname_len, &zcall, &num_args)) {
    3008               0 :                         return;
    3009                 :                 }
    3010               1 :                 DB_FROM_OBJECT(db, object);
    3011                 :         } else {
    3012               1 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) {
    3013               0 :                         return;
    3014                 :                 }
    3015               1 :                 DB_FROM_ZVAL(db, &zdb);
    3016                 :         }
    3017                 : 
    3018               2 :         if (!zend_is_callable(zcall, 0, &callable)) {
    3019               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function `%s' is not callable", callable);
    3020               0 :                 efree(callable);
    3021               0 :                 return;
    3022                 :         }
    3023               2 :         efree(callable);
    3024                 : 
    3025               2 :         if (prep_callback_struct(db, 0, funcname, zcall, NULL, &funcs) == DO_REG) {
    3026               2 :                 sqlite_create_function(db->db, funcname, num_args, php_sqlite_function_callback, funcs);
    3027                 :         }
    3028                 : }
    3029                 : /* }}} */
    3030                 : 
    3031                 : /* {{{ proto string sqlite_udf_encode_binary(string data)
    3032                 :    Apply binary encoding (if required) to a string to return from an UDF. */
    3033                 : PHP_FUNCTION(sqlite_udf_encode_binary)
    3034               5 : {
    3035               5 :         char *data = NULL;
    3036                 :         int datalen;
    3037                 : 
    3038               5 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
    3039               0 :                 return;
    3040                 :         }
    3041                 : 
    3042               5 :         if (data == NULL) {
    3043               0 :                 RETURN_NULL();
    3044                 :         }
    3045               8 :         if (datalen && (data[0] == '\x01' || memchr(data, '\0', datalen) != NULL)) {
    3046                 :                 /* binary string */
    3047                 :                 int enclen;
    3048                 :                 char *ret;
    3049                 : 
    3050               3 :                 ret = safe_emalloc(1 + datalen / 254, 257, 3);
    3051               3 :                 ret[0] = '\x01';
    3052               3 :                 enclen = php_sqlite_encode_binary(data, datalen, ret+1);
    3053               3 :                 RETVAL_STRINGL(ret, enclen+1, 0);
    3054                 :         } else {
    3055               2 :                 RETVAL_STRINGL(data, datalen, 1);
    3056                 :         }
    3057                 : }
    3058                 : /* }}} */
    3059                 : 
    3060                 : /* {{{ proto string sqlite_udf_decode_binary(string data)
    3061                 :    Decode binary encoding on a string parameter passed to an UDF. */
    3062                 : PHP_FUNCTION(sqlite_udf_decode_binary)
    3063               4 : {
    3064               4 :         char *data = NULL;
    3065                 :         int datalen;
    3066                 : 
    3067               4 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
    3068               0 :                 return;
    3069                 :         }
    3070                 : 
    3071               4 :         if (data == NULL) {
    3072               0 :                 RETURN_NULL();
    3073                 :         }
    3074               6 :         if (datalen && data[0] == '\x01') {
    3075                 :                 /* encoded string */
    3076                 :                 int enclen;
    3077                 :                 char *ret;
    3078                 : 
    3079               2 :                 ret = emalloc(datalen);
    3080               2 :                 enclen = php_sqlite_decode_binary(data+1, ret);
    3081               2 :                 ret[enclen] = '\0';
    3082               2 :                 RETVAL_STRINGL(ret, enclen, 0);
    3083                 :         } else {
    3084               2 :                 RETVAL_STRINGL(data, datalen, 1);
    3085                 :         }
    3086                 : }
    3087                 : /* }}} */
    3088                 : 
    3089                 : 
    3090                 : /*
    3091                 :  * Local variables:
    3092                 :  * tab-width: 4
    3093                 :  * c-basic-offset: 4
    3094                 :  * End:
    3095                 :  * vim600: sw=4 ts=4 fdm=marker
    3096                 :  * vim<600: sw=4 ts=4
    3097                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:20 +0000 (5 days ago)

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