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

LCOV - code coverage report
Current view: top level - ext/sqlite - sqlite.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 1035 1354 76.4 %
Date: 2014-07-27 Functions: 71 82 86.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:36 +0000 (23 hours ago)

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