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

LTP GCOV extension - code coverage report
Current view: directory - sqlite - sqlite.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 1338
Code covered: 76.5 % Executed lines: 1024
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Wez Furlong <wez@thebrainroom.com>                          |
      16                 :    |          Tal Peer <tal@php.net>                                      |
      17                 :    |          Marcus Boerger <helly@php.net>                              |
      18                 :    +----------------------------------------------------------------------+
      19                 : 
      20                 :    $Id: sqlite.c 289587 2009-10-12 19:04:00Z felipe $
      21                 : */
      22                 : 
      23                 : #ifdef HAVE_CONFIG_H
      24                 : #include "config.h"
      25                 : #endif
      26                 : 
      27                 : #define PHP_SQLITE_MODULE_VERSION       "2.0-dev"
      28                 : 
      29                 : #include "php.h"
      30                 : #include "php_ini.h"
      31                 : #include "ext/standard/info.h"
      32                 : #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
      33                 : #include "ext/session/php_session.h"
      34                 : #endif
      35                 : #include "php_sqlite.h"
      36                 : 
      37                 : #if HAVE_TIME_H
      38                 : # include <time.h>
      39                 : #endif
      40                 : #if HAVE_UNISTD_H
      41                 : #include <unistd.h>
      42                 : #endif
      43                 : 
      44                 : #include <sqlite.h>
      45                 : 
      46                 : #include "zend_exceptions.h"
      47                 : #include "zend_interfaces.h"
      48                 : 
      49                 : #if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
      50                 : extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
      51                 : extern PHPAPI zend_class_entry *spl_ce_Countable;
      52                 : #endif
      53                 : 
      54                 : #if PHP_SQLITE2_HAVE_PDO
      55                 : # include "pdo/php_pdo.h"
      56                 : # include "pdo/php_pdo_driver.h"
      57                 : extern pdo_driver_t pdo_sqlite2_driver;
      58                 : #endif
      59                 : 
      60                 : #ifndef safe_emalloc
      61                 : # define safe_emalloc(a,b,c) emalloc((a)*(b)+(c))
      62                 : #endif
      63                 : 
      64                 : ZEND_DECLARE_MODULE_GLOBALS(sqlite)
      65                 : static PHP_GINIT_FUNCTION(sqlite);
      66                 : 
      67                 : #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
      68                 : extern ps_module ps_mod_sqlite;
      69                 : #define ps_sqlite_ptr &ps_mod_sqlite
      70                 : #endif
      71                 : 
      72                 : extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
      73                 : extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
      74                 : 
      75                 : #define php_sqlite_encode_binary(in, n, out) sqlite_encode_binary((const unsigned char *)in, n, (unsigned char *)out)
      76                 : #define php_sqlite_decode_binary(in, out) in && *in ? sqlite_decode_binary((const unsigned char *)in, (unsigned char *)out) : 0
      77                 : 
      78                 : static int sqlite_count_elements(zval *object, long *count TSRMLS_DC);
      79                 : 
      80                 : static int le_sqlite_db, le_sqlite_result, le_sqlite_pdb;
      81                 : 
      82                 : static inline void php_sqlite_strtoupper(char *s)
      83               0 : {
      84               0 :         while (*s!='\0') {
      85               0 :                 *s = toupper(*s);
      86               0 :                 s++;
      87                 :         }
      88               0 : }
      89                 : 
      90                 : static inline void php_sqlite_strtolower(char *s)
      91               0 : {
      92               0 :         while (*s!='\0') {
      93               0 :                 *s = tolower(*s);
      94               0 :                 s++;
      95                 :         }
      96               0 : }
      97                 : 
      98                 : /* {{{ PHP_INI
      99                 :  */
     100                 : PHP_INI_BEGIN()
     101                 : STD_PHP_INI_ENTRY_EX("sqlite.assoc_case", "0", PHP_INI_ALL, OnUpdateLong, assoc_case, zend_sqlite_globals, sqlite_globals, display_link_numbers)
     102                 : PHP_INI_END()
     103                 : /* }}} */
     104                 : 
     105                 : #define DB_FROM_ZVAL(db, zv)    ZEND_FETCH_RESOURCE2(db, struct php_sqlite_db *, zv, -1, "sqlite database", le_sqlite_db, le_sqlite_pdb)
     106                 : 
     107                 : #define DB_FROM_OBJECT(db, object) \
     108                 :         { \
     109                 :                 sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
     110                 :                 db = obj->u.db; \
     111                 :                 if (!db) { \
     112                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "The database wasn't opened"); \
     113                 :                         RETURN_NULL(); \
     114                 :                 } \
     115                 :         }
     116                 : 
     117                 : #define RES_FROM_OBJECT_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                 : static int php_sqlite_callback_invalidator(struct php_sqlite_agg_functions *funcs TSRMLS_DC)
     643               5 : {
     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                 : static void php_sqlite_callback_dtor(void *pDest)
     665               5 : {
     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                 : static ZEND_RSRC_DTOR_FUNC(php_sqlite_db_dtor)
     676              62 : {
     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                 : static void real_result_dtor(struct php_sqlite_result *res TSRMLS_DC)
     691              97 : {
     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                 : static int _clean_unfinished_results(zend_rsrc_list_entry *le, void *db TSRMLS_DC)
     726             132 : {
     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                 : static ZEND_RSRC_DTOR_FUNC(php_sqlite_result_dtor)
     737              32 : {
     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                 : static int php_sqlite_forget_persistent_id_numbers(zend_rsrc_list_entry *rsrc TSRMLS_DC)
     743             328 : {
     744             328 :         struct php_sqlite_db *db = (struct php_sqlite_db*)rsrc->ptr;
     745                 : 
     746             328 :         if (Z_TYPE_P(rsrc) != le_sqlite_pdb) {
     747             327 :                 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                 : PHP_RSHUTDOWN_FUNCTION(sqlite)
     762           17651 : {
     763           17651 :         zend_hash_apply(&EG(persistent_list), (apply_func_t)php_sqlite_forget_persistent_id_numbers TSRMLS_CC);
     764           17651 :         return SUCCESS;
     765                 : }
     766                 : 
     767                 : /* {{{ PHP Function interface */
     768                 : static void php_sqlite_generic_function_callback(sqlite_func *func, int argc, const char **argv)
     769               7 : {
     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                 :                         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                 : static void php_sqlite_function_callback(sqlite_func *func, int argc, const char **argv)
     859               7 : {
     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                 : static void php_sqlite_agg_step_function_callback(sqlite_func *func, int argc, const char **argv)
     935               6 : {
     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                 : static void php_sqlite_agg_fini_function_callback(sqlite_func *func)
    1006               2 : {
    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                 : static int php_sqlite_authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
    1063                 :                 const char *arg5, const char *arg6)
    1064               0 : {
    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                 : static int sqlite_free_persistent(zend_rsrc_list_entry *le, void *ptr TSRMLS_DC)
    1136               0 : {
    1137               0 :         return le->ptr == ptr ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_KEEP;
    1138                 : }
    1139                 : 
    1140                 : static void sqlite_object_free_storage(void *object TSRMLS_DC)
    1141              69 : {
    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                 : static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC)
    1161              69 : {
    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_add_ref, (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                 : static zend_object_value sqlite_object_new_db(zend_class_entry *class_type TSRMLS_DC)
    1176              29 : {
    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                 : static zend_object_value sqlite_object_new_query(zend_class_entry *class_type TSRMLS_DC)
    1184              17 : {
    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                 : static zend_object_value sqlite_object_new_ub_query(zend_class_entry *class_type TSRMLS_DC)
    1192              23 : {
    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                 : static zend_object_value sqlite_object_new_exception(zend_class_entry *class_type TSRMLS_DC)
    1200               0 : {
    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                 : static zend_class_entry *sqlite_get_ce_query(const zval *object TSRMLS_DC)
    1216              79 : {
    1217              79 :         return sqlite_ce_query;
    1218                 : }
    1219                 : 
    1220                 : static zend_class_entry *sqlite_get_ce_ub_query(const zval *object TSRMLS_DC)
    1221              78 : {
    1222              78 :         return sqlite_ce_ub_query;
    1223                 : }
    1224                 : 
    1225                 : static zval * sqlite_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
    1226              40 : {
    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              40 :         Z_SET_REFCOUNT_P(object, 1);
    1233              40 :         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                 : void sqlite_iterator_dtor(zend_object_iterator *iter TSRMLS_DC)
    1244               6 : {
    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                 : void sqlite_iterator_rewind(zend_object_iterator *iter TSRMLS_DC)
    1256               2 : {
    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                 : int sqlite_iterator_valid(zend_object_iterator *iter TSRMLS_DC)
    1269              21 : {
    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                 : void sqlite_iterator_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
    1280              15 : {
    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                 : int sqlite_iterator_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
    1292               3 : {
    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                 : void sqlite_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC)
    1302              15 : {
    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                 : zend_object_iterator *sqlite_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
    1341               6 : {
    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               6 :         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                 : static PHP_GINIT_FUNCTION(sqlite)
    1359           17633 : {
    1360           17633 :         sqlite_globals->assoc_case = 0;
    1361           17633 : }
    1362                 : 
    1363                 : PHP_MINIT_FUNCTION(sqlite)
    1364           17633 : {
    1365           17633 :         REGISTER_SQLITE_CLASS(Database,   db,        NULL);
    1366           17633 :         REGISTER_SQLITE_CLASS(Result,     query,     NULL);
    1367           17633 :         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           17633 :         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           17633 :         sqlite_ce_db->ce_flags &= ~ZEND_ACC_FINAL_CLASS;
    1375           17633 :         sqlite_ce_db->constructor->common.fn_flags |= ZEND_ACC_FINAL;
    1376                 : 
    1377           17633 :         sqlite_object_handlers_query.get_class_entry = sqlite_get_ce_query;
    1378           17633 :         sqlite_object_handlers_ub_query.get_class_entry = sqlite_get_ce_ub_query;
    1379           17633 :         sqlite_object_handlers_ub_query.count_elements = sqlite_count_elements;
    1380                 : 
    1381           17633 :         sqlite_ce_ub_query->get_iterator = sqlite_get_iterator;
    1382           17633 :         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           17633 :         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           17633 :         sqlite_ce_query->get_iterator = sqlite_get_iterator;
    1390           17633 :         sqlite_ce_query->iterator_funcs.funcs = &sqlite_query_iterator_funcs;
    1391                 : 
    1392           17633 :         REGISTER_INI_ENTRIES();
    1393                 : 
    1394                 : #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
    1395           17633 :         php_session_register_module(ps_sqlite_ptr);
    1396                 : #endif
    1397                 : 
    1398           17633 :         le_sqlite_db = zend_register_list_destructors_ex(php_sqlite_db_dtor, NULL, "sqlite database", module_number);
    1399           17633 :         le_sqlite_pdb = zend_register_list_destructors_ex(NULL, php_sqlite_db_dtor, "sqlite database (persistent)", module_number);
    1400           17633 :         le_sqlite_result = zend_register_list_destructors_ex(php_sqlite_result_dtor, NULL, "sqlite result", module_number);
    1401                 : 
    1402           17633 :         REGISTER_LONG_CONSTANT("SQLITE_BOTH", PHPSQLITE_BOTH, CONST_CS|CONST_PERSISTENT);
    1403           17633 :         REGISTER_LONG_CONSTANT("SQLITE_NUM",  PHPSQLITE_NUM, CONST_CS|CONST_PERSISTENT);
    1404           17633 :         REGISTER_LONG_CONSTANT("SQLITE_ASSOC",        PHPSQLITE_ASSOC, CONST_CS|CONST_PERSISTENT);
    1405                 : 
    1406           17633 :         REGISTER_LONG_CONSTANT("SQLITE_OK",                           SQLITE_OK, CONST_CS|CONST_PERSISTENT);
    1407           17633 :         REGISTER_LONG_CONSTANT("SQLITE_ERROR",                        SQLITE_ERROR, CONST_CS|CONST_PERSISTENT);
    1408           17633 :         REGISTER_LONG_CONSTANT("SQLITE_INTERNAL",             SQLITE_INTERNAL, CONST_CS|CONST_PERSISTENT);
    1409           17633 :         REGISTER_LONG_CONSTANT("SQLITE_PERM",                 SQLITE_PERM, CONST_CS|CONST_PERSISTENT);
    1410           17633 :         REGISTER_LONG_CONSTANT("SQLITE_ABORT",                        SQLITE_ABORT, CONST_CS|CONST_PERSISTENT);
    1411           17633 :         REGISTER_LONG_CONSTANT("SQLITE_BUSY",                 SQLITE_BUSY, CONST_CS|CONST_PERSISTENT);
    1412           17633 :         REGISTER_LONG_CONSTANT("SQLITE_LOCKED",                       SQLITE_LOCKED, CONST_CS|CONST_PERSISTENT);
    1413           17633 :         REGISTER_LONG_CONSTANT("SQLITE_NOMEM",                        SQLITE_NOMEM, CONST_CS|CONST_PERSISTENT);
    1414           17633 :         REGISTER_LONG_CONSTANT("SQLITE_READONLY",             SQLITE_READONLY, CONST_CS|CONST_PERSISTENT);
    1415           17633 :         REGISTER_LONG_CONSTANT("SQLITE_INTERRUPT",            SQLITE_INTERRUPT, CONST_CS|CONST_PERSISTENT);
    1416           17633 :         REGISTER_LONG_CONSTANT("SQLITE_IOERR",                        SQLITE_IOERR, CONST_CS|CONST_PERSISTENT);
    1417           17633 :         REGISTER_LONG_CONSTANT("SQLITE_CORRUPT",              SQLITE_CORRUPT, CONST_CS|CONST_PERSISTENT);
    1418           17633 :         REGISTER_LONG_CONSTANT("SQLITE_NOTFOUND",             SQLITE_NOTFOUND, CONST_CS|CONST_PERSISTENT);
    1419           17633 :         REGISTER_LONG_CONSTANT("SQLITE_FULL",                 SQLITE_FULL, CONST_CS|CONST_PERSISTENT);
    1420           17633 :         REGISTER_LONG_CONSTANT("SQLITE_CANTOPEN",             SQLITE_CANTOPEN, CONST_CS|CONST_PERSISTENT);
    1421           17633 :         REGISTER_LONG_CONSTANT("SQLITE_PROTOCOL",             SQLITE_PROTOCOL, CONST_CS|CONST_PERSISTENT);
    1422           17633 :         REGISTER_LONG_CONSTANT("SQLITE_EMPTY",                        SQLITE_EMPTY, CONST_CS|CONST_PERSISTENT);
    1423           17633 :         REGISTER_LONG_CONSTANT("SQLITE_SCHEMA",                       SQLITE_SCHEMA, CONST_CS|CONST_PERSISTENT);
    1424           17633 :         REGISTER_LONG_CONSTANT("SQLITE_TOOBIG",                       SQLITE_TOOBIG, CONST_CS|CONST_PERSISTENT);
    1425           17633 :         REGISTER_LONG_CONSTANT("SQLITE_CONSTRAINT",           SQLITE_CONSTRAINT, CONST_CS|CONST_PERSISTENT);
    1426           17633 :         REGISTER_LONG_CONSTANT("SQLITE_MISMATCH",             SQLITE_MISMATCH, CONST_CS|CONST_PERSISTENT);
    1427           17633 :         REGISTER_LONG_CONSTANT("SQLITE_MISUSE",                       SQLITE_MISUSE, CONST_CS|CONST_PERSISTENT);
    1428           17633 :         REGISTER_LONG_CONSTANT("SQLITE_NOLFS",                        SQLITE_NOLFS, CONST_CS|CONST_PERSISTENT);
    1429           17633 :         REGISTER_LONG_CONSTANT("SQLITE_AUTH",                 SQLITE_AUTH, CONST_CS|CONST_PERSISTENT);
    1430           17633 :         REGISTER_LONG_CONSTANT("SQLITE_NOTADB",                       SQLITE_NOTADB, CONST_CS|CONST_PERSISTENT);
    1431                 : #ifdef SQLITE_FORMAT
    1432           17633 :         REGISTER_LONG_CONSTANT("SQLITE_FORMAT",                       SQLITE_FORMAT, CONST_CS|CONST_PERSISTENT);
    1433                 : #endif
    1434           17633 :         REGISTER_LONG_CONSTANT("SQLITE_ROW",                  SQLITE_ROW, CONST_CS|CONST_PERSISTENT);
    1435           17633 :         REGISTER_LONG_CONSTANT("SQLITE_DONE",                 SQLITE_DONE, CONST_CS|CONST_PERSISTENT);
    1436                 : 
    1437                 : #ifdef PHP_SQLITE2_HAVE_PDO
    1438           17633 :     if (FAILURE == php_pdo_register_driver(&pdo_sqlite2_driver)) {
    1439               0 :         return FAILURE;
    1440                 :     }
    1441                 : #endif
    1442                 : 
    1443           17633 :         return SUCCESS;
    1444                 : }
    1445                 : 
    1446                 : PHP_MSHUTDOWN_FUNCTION(sqlite)
    1447           17665 : {
    1448           17665 :         UNREGISTER_INI_ENTRIES();
    1449                 : 
    1450                 : #ifdef PHP_SQLITE2_HAVE_PDO
    1451           17665 :     php_pdo_unregister_driver(&pdo_sqlite2_driver);
    1452                 : #endif
    1453                 : 
    1454           17665 :         return SUCCESS;
    1455                 : }
    1456                 : 
    1457                 : PHP_MINFO_FUNCTION(sqlite)
    1458              42 : {
    1459              42 :         php_info_print_table_start();
    1460              42 :         php_info_print_table_header(2, "SQLite support", "enabled");
    1461              42 :         php_info_print_table_row(2, "PECL Module version", PHP_SQLITE_MODULE_VERSION " $Id: sqlite.c 289587 2009-10-12 19:04:00Z felipe $");
    1462              42 :         php_info_print_table_row(2, "SQLite Library", sqlite_libversion());
    1463              42 :         php_info_print_table_row(2, "SQLite Encoding", sqlite_libencoding());
    1464              42 :         php_info_print_table_end();
    1465                 : 
    1466              42 :         DISPLAY_INI_ENTRIES();
    1467              42 : }
    1468                 : 
    1469                 : 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              62 : {
    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                 : PHP_FUNCTION(sqlite_popen)
    1546               5 : {
    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 (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
    1564                 :                 /* resolve the fully-qualified path name to use as the hash key */
    1565               1 :                 if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
    1566               1 :                         RETURN_FALSE;
    1567                 :                 }
    1568                 : 
    1569               0 :                 if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || 
    1570                 :                                 php_check_open_basedir(fullpath TSRMLS_CC)) {
    1571               0 :                         efree(fullpath);
    1572               0 :                         RETURN_FALSE;
    1573                 :                 }
    1574                 :         } else {
    1575               2 :                 fullpath = estrndup(filename, filename_len);
    1576                 :         }
    1577                 : 
    1578               2 :         hashkeylen = spprintf(&hashkey, 0, "sqlite_pdb_%s:%ld", fullpath, mode);
    1579                 : 
    1580                 :         /* do we have an existing persistent connection ? */
    1581               2 :         if (SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, hashkeylen+1, (void*)&le)) {
    1582               1 :                 if (Z_TYPE_P(le) == le_sqlite_pdb) {
    1583               1 :                         db = (struct php_sqlite_db*)le->ptr;
    1584                 : 
    1585               1 :                         if (db->rsrc_id == FAILURE) {
    1586                 :                                 /* give it a valid resource id for this request */
    1587               0 :                                 db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, le_sqlite_pdb);
    1588                 :                         } else {
    1589                 :                                 int type;
    1590                 :                                 /* sanity check to ensure that the resource is still a valid regular resource
    1591                 :                                  * number */
    1592               1 :                                 if (zend_list_find(db->rsrc_id, &type) == db) {
    1593                 :                                         /* already accessed this request; map it */
    1594               1 :                                         zend_list_addref(db->rsrc_id);
    1595               1 :                                         ZVAL_RESOURCE(return_value, db->rsrc_id);
    1596                 :                                 } else {
    1597               0 :                                         db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, le_sqlite_pdb);
    1598                 :                                 }
    1599                 :                         }
    1600                 : 
    1601                 :                         /* all set */
    1602               1 :                         goto done;
    1603                 :                 }
    1604                 : 
    1605               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Some other type of persistent resource is using this hash key!?");
    1606               0 :                 RETVAL_FALSE;
    1607               0 :                 goto done;
    1608                 :         }
    1609                 : 
    1610                 :         /* now we need to open the database */
    1611               1 :         php_sqlite_open(fullpath, (int)mode, hashkey, return_value, errmsg, NULL TSRMLS_CC);
    1612               2 : done:
    1613               2 :         efree(fullpath);
    1614               2 :         efree(hashkey);
    1615                 : }
    1616                 : /* }}} */
    1617                 : 
    1618                 : /* {{{ proto resource sqlite_open(string filename [, int mode [, string &error_message]])
    1619                 :    Opens a SQLite database. Will create the database if it does not exist. */
    1620                 : PHP_FUNCTION(sqlite_open)
    1621              60 : {
    1622              60 :         long mode = 0666;
    1623              60 :         char *filename, *fullpath = NULL;
    1624                 :         int filename_len;
    1625              60 :         zval *errmsg = NULL;
    1626              60 :         zval *object = getThis();
    1627                 :         zend_error_handling error_handling;
    1628                 : 
    1629              60 :         zend_replace_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception, &error_handling TSRMLS_CC);
    1630              60 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
    1631                 :                                 &filename, &filename_len, &mode, &errmsg)) {
    1632               0 :                 zend_restore_error_handling(&error_handling TSRMLS_CC);
    1633               0 :                 return;
    1634                 :         }
    1635              60 :         if (errmsg) {
    1636               1 :                 zval_dtor(errmsg);
    1637               1 :                 ZVAL_NULL(errmsg);
    1638                 :         }
    1639                 : 
    1640              60 :         if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
    1641                 :                 /* resolve the fully-qualified path name to use as the hash key */
    1642               0 :                 if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
    1643               0 :                         zend_restore_error_handling(&error_handling TSRMLS_CC);
    1644               0 :                         if (object) {
    1645               0 :                                 RETURN_NULL();
    1646                 :                         } else {
    1647               0 :                                 RETURN_FALSE;
    1648                 :                         }
    1649                 :                 }
    1650                 : 
    1651               0 :                 if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
    1652                 :                                 php_check_open_basedir(fullpath TSRMLS_CC)) {
    1653               0 :                         efree(fullpath);
    1654               0 :                         zend_restore_error_handling(&error_handling TSRMLS_CC);
    1655               0 :                         if (object) {
    1656               0 :                                 RETURN_NULL();
    1657                 :                         } else {
    1658               0 :                                 RETURN_FALSE;
    1659                 :                         }
    1660                 :                 }
    1661                 :         }
    1662                 : 
    1663              60 :         php_sqlite_open(fullpath ? fullpath : filename, (int)mode, NULL, return_value, errmsg, object TSRMLS_CC);
    1664                 : 
    1665              60 :         if (fullpath) {
    1666               0 :                 efree(fullpath);
    1667                 :         }
    1668              60 :         zend_restore_error_handling(&error_handling TSRMLS_CC);
    1669                 : }
    1670                 : /* }}} */
    1671                 : 
    1672                 : /* {{{ proto object sqlite_factory(string filename [, int mode [, string &error_message]])
    1673                 :    Opens a SQLite database and creates an object for it. Will create the database if it does not exist. */
    1674                 : PHP_FUNCTION(sqlite_factory)
    1675               3 : {
    1676               3 :         long mode = 0666;
    1677               3 :         char *filename, *fullpath = NULL;
    1678                 :         int filename_len;
    1679               3 :         zval *errmsg = NULL;
    1680                 :         zend_error_handling error_handling;
    1681                 : 
    1682               3 :         zend_replace_error_handling(EH_THROW, sqlite_ce_exception, &error_handling TSRMLS_CC);
    1683               3 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
    1684                 :                                 &filename, &filename_len, &mode, &errmsg)) {
    1685               2 :                 zend_restore_error_handling(&error_handling TSRMLS_CC);
    1686               2 :                 RETURN_NULL();
    1687                 :         }
    1688               1 :         if (errmsg) {
    1689               0 :                 zval_dtor(errmsg);
    1690               0 :                 ZVAL_NULL(errmsg);
    1691                 :         }
    1692                 : 
    1693               1 :         if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
    1694                 :                 /* resolve the fully-qualified path name to use as the hash key */
    1695               1 :                 if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
    1696               0 :                         zend_restore_error_handling(&error_handling TSRMLS_CC);
    1697               0 :                         RETURN_NULL();
    1698                 :                 }
    1699                 : 
    1700               1 :                 if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
    1701                 :                                 php_check_open_basedir(fullpath TSRMLS_CC)) {
    1702               0 :                         efree(fullpath);
    1703               0 :                         zend_restore_error_handling(&error_handling TSRMLS_CC);
    1704               0 :                         RETURN_NULL();
    1705                 :                 }
    1706                 :         }
    1707                 : 
    1708               1 :         php_sqlite_open(fullpath ? fullpath : filename, (int)mode, NULL, return_value, errmsg, return_value TSRMLS_CC);
    1709               1 :         if (fullpath) {
    1710               1 :                 efree(fullpath);
    1711                 :         }
    1712               1 :         zend_restore_error_handling(&error_handling TSRMLS_CC);
    1713                 : }
    1714                 : /* }}} */
    1715                 : 
    1716                 : /* {{{ proto void sqlite_busy_timeout(resource db, int ms)
    1717                 :    Set busy timeout duration. If ms <= 0, all busy handlers are disabled. */
    1718                 : PHP_FUNCTION(sqlite_busy_timeout)
    1719               0 : {
    1720                 :         zval *zdb;
    1721                 :         struct php_sqlite_db *db;
    1722                 :         long ms;
    1723               0 :         zval *object = getThis();
    1724                 : 
    1725               0 :         if (object) {
    1726               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ms)) {
    1727               0 :                         return;
    1728                 :                 }
    1729               0 :                 DB_FROM_OBJECT(db, object);
    1730                 :         } else {
    1731               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zdb, &ms)) {
    1732               0 :                         return;
    1733                 :                 }
    1734               0 :                 DB_FROM_ZVAL(db, &zdb);
    1735                 :         }
    1736                 : 
    1737               0 :         sqlite_busy_timeout(db->db, ms);
    1738                 : }
    1739                 : /* }}} */
    1740                 : 
    1741                 : /* {{{ proto void sqlite_close(resource db)
    1742                 :    Closes an open sqlite database. */
    1743                 : PHP_FUNCTION(sqlite_close)
    1744              28 : {
    1745                 :         zval *zdb;
    1746                 :         struct php_sqlite_db *db;
    1747              28 :         zval *object = getThis();
    1748                 : 
    1749              28 :         if (object) {
    1750               0 :                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Ignored, you must destruct the object instead");
    1751                 :         } else {
    1752              28 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
    1753               0 :                         return;
    1754                 :                 }
    1755              28 :                 DB_FROM_ZVAL(db, &zdb);
    1756                 :         }
    1757                 : 
    1758              28 :         zend_hash_apply_with_argument(&EG(regular_list),
    1759                 :                 (apply_func_arg_t) _clean_unfinished_results,
    1760                 :                 db TSRMLS_CC);
    1761                 : 
    1762              28 :         zend_list_delete(Z_RESVAL_P(zdb));
    1763                 : }
    1764                 : /* }}} */
    1765                 : 
    1766                 : /* {{{ php_sqlite_fetch */
    1767                 : static int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC)
    1768             188 : {
    1769                 :         const char **rowdata, **colnames;
    1770                 :         int ret, i, base;
    1771             188 :         char *errtext = NULL;
    1772                 : 
    1773             267 : next_row:
    1774             267 :         ret = sqlite_step(rres->vm, &rres->ncolumns, &rowdata, &colnames);
    1775             267 :         if (!rres->nrows) {
    1776                 :                 /* first row - lets copy the column names */
    1777              97 :                 rres->col_names = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
    1778             268 :                 for (i = 0; i < rres->ncolumns; i++) {
    1779             171 :                         rres->col_names[i] = estrdup((char*)colnames[i]);
    1780                 : 
    1781             171 :                         if (SQLITE_G(assoc_case) == 1) {
    1782               0 :                                 php_sqlite_strtoupper(rres->col_names[i]);
    1783             171 :                         } else if (SQLITE_G(assoc_case) == 2) {
    1784               0 :                                 php_sqlite_strtolower(rres->col_names[i]);
    1785                 :                         }
    1786                 :                 }
    1787              97 :                 if (!rres->buffered) {
    1788                 :                         /* non buffered mode - also fetch memory for on single row */
    1789              59 :                         rres->table = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
    1790                 :                 }
    1791                 :         }
    1792                 : 
    1793             267 :         switch (ret) {
    1794                 :                 case SQLITE_ROW:
    1795             170 :                         if (rres->buffered) {
    1796                 :                                 /* add the row to our collection */
    1797              79 :                                 if (rres->nrows + 1 >= rres->alloc_rows) {
    1798              34 :                                         rres->alloc_rows = rres->alloc_rows ? rres->alloc_rows * 2 : 16;
    1799              34 :                                         rres->table = safe_erealloc(rres->table, rres->alloc_rows, rres->ncolumns*sizeof(char *), 0);
    1800                 :                                 }
    1801              79 :                                 base = rres->nrows * rres->ncolumns;
    1802             204 :                                 for (i = 0; i < rres->ncolumns; i++) {
    1803             125 :                                         if (rowdata[i]) {
    1804             117 :                                                 rres->table[base + i] = estrdup(rowdata[i]);
    1805                 :                                         } else {
    1806               8 :                                                 rres->table[base + i] = NULL;
    1807                 :                                         }
    1808                 :                                 }
    1809              79 :                                 rres->nrows++;
    1810              79 :                                 goto next_row;
    1811                 :                         } else {
    1812                 :                                 /* non buffered: only fetch one row but first free data if not first row */
    1813              91 :                                 if (rres->nrows++) {
    1814              93 :                                         for (i = 0; i < rres->ncolumns; i++) {
    1815              52 :                                                 if (rres->table[i]) {
    1816               8 :                                                         efree(rres->table[i]);
    1817                 :                                                 }
    1818                 :                                         }
    1819                 :                                 }
    1820             220 :                                 for (i = 0; i < rres->ncolumns; i++) {
    1821             129 :                                         if (rowdata[i]) {
    1822             124 :                                                 rres->table[i] = estrdup(rowdata[i]);
    1823                 :                                         } else {
    1824               5 :                                                 rres->table[i] = NULL;
    1825                 :                                         }
    1826                 :                                 }
    1827                 :                         }
    1828              91 :                         ret = SQLITE_OK;
    1829              91 :                         break;
    1830                 : 
    1831                 :                 case SQLITE_BUSY:
    1832                 :                 case SQLITE_ERROR:
    1833                 :                 case SQLITE_MISUSE:
    1834                 :                 case SQLITE_DONE:
    1835                 :                 default:
    1836              97 :                         if (rres->vm) {
    1837              97 :                                 ret = sqlite_finalize(rres->vm, &errtext);
    1838                 :                         }
    1839              97 :                         rres->vm = NULL;
    1840              97 :                         if (ret != SQLITE_OK) {
    1841               1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1842               1 :                                 sqlite_freemem(errtext);
    1843                 :                         }
    1844                 :                         break;
    1845                 :         }
    1846             188 :         rres->db->last_err_code = ret;
    1847                 : 
    1848             188 :         return ret;
    1849                 : }
    1850                 : /* }}} */
    1851                 : 
    1852                 : /* {{{ sqlite_query */
    1853                 : 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)
    1854             102 : {
    1855                 :         struct php_sqlite_result res, *rres;
    1856                 :         int ret;
    1857             102 :         char *errtext = NULL;
    1858                 :         const char *tail;
    1859                 : 
    1860             102 :         memset(&res, 0, sizeof(res));
    1861             102 :         res.buffered = buffered;
    1862             102 :         res.mode = mode;
    1863                 : 
    1864             102 :         ret = sqlite_compile(db->db, sql, &tail, &res.vm, &errtext);
    1865             102 :         db->last_err_code = ret;
    1866                 : 
    1867             102 :         if (ret != SQLITE_OK) {
    1868               4 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1869               4 :                 if (errmsg) {
    1870               2 :                         ZVAL_STRING(errmsg, errtext, 1);
    1871                 :                 }
    1872               4 :                 sqlite_freemem(errtext);
    1873               4 :                 goto terminate;
    1874              98 :         } else if (!res.vm) { /* empty query */
    1875               5 : terminate:
    1876               5 :                 if (return_value) {
    1877               3 :                         RETURN_FALSE;
    1878                 :                 } else {
    1879               2 :                         return;
    1880                 :                 }
    1881                 :         }
    1882                 : 
    1883              97 :         if (!prres) {
    1884              71 :                 rres = NULL;
    1885              71 :                 prres = &rres;
    1886                 :         }
    1887              97 :         if (!*prres) {
    1888              71 :                 *prres = (struct php_sqlite_result*)emalloc(sizeof(**prres));
    1889                 :         }
    1890              97 :         memcpy(*prres, &res, sizeof(**prres));
    1891              97 :         (*prres)->db = db;
    1892              97 :         zend_list_addref(db->rsrc_id);
    1893                 : 
    1894                 : 
    1895                 :         /* now the result set is ready for stepping: get first row */
    1896              97 :         if (php_sqlite_fetch((*prres) TSRMLS_CC) != SQLITE_OK) {
    1897               1 :                 real_result_dtor((*prres) TSRMLS_CC);
    1898               1 :                 *prres = NULL;
    1899               1 :                 if (return_value) {
    1900               0 :                         RETURN_FALSE;
    1901                 :                 } else {
    1902               1 :                         return;
    1903                 :                 }
    1904                 :         }
    1905                 : 
    1906              96 :         (*prres)->curr_row = 0;
    1907                 : 
    1908              96 :         if (object) {
    1909                 :                 sqlite_object *obj;
    1910              39 :                 if (buffered) {
    1911              17 :                         sqlite_instanciate(sqlite_ce_query, return_value TSRMLS_CC);
    1912                 :                 } else {
    1913              22 :                         sqlite_instanciate(sqlite_ce_ub_query, return_value TSRMLS_CC);
    1914                 :                 }
    1915              39 :                 obj = (sqlite_object *) zend_object_store_get_object(return_value TSRMLS_CC);
    1916              39 :                 obj->type = is_result;
    1917              39 :                 obj->u.res = (*prres);
    1918              57 :         } else if (return_value) {
    1919              32 :                 ZEND_REGISTER_RESOURCE(object ? NULL : return_value, (*prres), le_sqlite_result);
    1920                 :         }
    1921                 : }
    1922                 : /* }}} */
    1923                 : 
    1924                 : /* {{{ proto resource sqlite_unbuffered_query(string query, resource db [ , int result_type [, string &error_message]])
    1925                 :    Executes a query that does not prefetch and buffer all data. */
    1926                 : PHP_FUNCTION(sqlite_unbuffered_query)
    1927              34 : {
    1928                 :         zval *zdb;
    1929                 :         struct php_sqlite_db *db;
    1930                 :         char *sql;
    1931                 :         int sql_len;
    1932              34 :         long mode = PHPSQLITE_BOTH;
    1933              34 :         char *errtext = NULL;
    1934              34 :         zval *errmsg = NULL;
    1935              34 :         zval *object = getThis();
    1936                 : 
    1937              34 :         if (object) {
    1938              22 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
    1939               0 :                         return;
    1940                 :                 }
    1941              22 :                 DB_FROM_OBJECT(db, object);
    1942                 :         } else {
    1943              12 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    1944                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
    1945                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
    1946               0 :                         return;
    1947                 :                 }
    1948              12 :                 DB_FROM_ZVAL(db, &zdb);
    1949                 :         }
    1950                 : 
    1951              34 :         if (errmsg) {
    1952               1 :                 zval_dtor(errmsg);
    1953               1 :                 ZVAL_NULL(errmsg);
    1954                 :         }
    1955                 : 
    1956              34 :         PHP_SQLITE_EMPTY_QUERY;
    1957                 : 
    1958                 :         /* avoid doing work if we can */
    1959              34 :         if (!return_value_used) {
    1960               0 :                 db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    1961                 : 
    1962               0 :                 if (db->last_err_code != SQLITE_OK) {
    1963               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    1964               0 :                         if (errmsg) {
    1965               0 :                                 ZVAL_STRING(errmsg, errtext, 1);
    1966                 :                         }
    1967               0 :                         sqlite_freemem(errtext);
    1968                 :                 }
    1969               0 :                 return;
    1970                 :         }
    1971                 : 
    1972              34 :         sqlite_query(object, db, sql, sql_len, (int)mode, 0, return_value, NULL, errmsg TSRMLS_CC);
    1973                 : }
    1974                 : /* }}} */
    1975                 : 
    1976                 : /* {{{ proto resource sqlite_fetch_column_types(string table_name, resource db [, int result_type])
    1977                 :    Return an array of column types from a particular table. */
    1978                 : PHP_FUNCTION(sqlite_fetch_column_types)
    1979               2 : {
    1980                 :         zval *zdb;
    1981                 :         struct php_sqlite_db *db;
    1982                 :         char *tbl, *sql;
    1983                 :         int tbl_len;
    1984               2 :         char *errtext = NULL;
    1985               2 :         zval *object = getThis();
    1986                 :         struct php_sqlite_result res;
    1987                 :         const char **rowdata, **colnames, *tail;
    1988                 :         int i, ncols;
    1989               2 :         long result_type = PHPSQLITE_ASSOC;
    1990                 : 
    1991               2 :         if (object) {
    1992               1 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &tbl, &tbl_len, &result_type)) {
    1993               0 :                         return;
    1994                 :                 }
    1995               1 :                 DB_FROM_OBJECT(db, object);
    1996                 :         } else {
    1997               1 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    1998                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &tbl, &tbl_len, &zdb, &result_type) &&
    1999                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &tbl, &tbl_len, &result_type)) {
    2000               0 :                         return;
    2001                 :                 }
    2002               1 :                 DB_FROM_ZVAL(db, &zdb);
    2003                 :         }
    2004                 : 
    2005               2 :         if (!(sql = sqlite_mprintf("SELECT * FROM '%q' LIMIT 1", tbl))) {
    2006               0 :                 RETURN_FALSE;
    2007                 :         }
    2008                 : 
    2009               2 :         sqlite_exec(db->db, "PRAGMA show_datatypes = ON", NULL, NULL, NULL);
    2010                 : 
    2011               2 :         db->last_err_code = sqlite_compile(db->db, sql, &tail, &res.vm, &errtext);
    2012                 : 
    2013               2 :         sqlite_freemem(sql);
    2014                 : 
    2015               2 :         if (db->last_err_code != SQLITE_OK) {
    2016               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    2017               0 :                 sqlite_freemem(errtext);
    2018               0 :                 RETVAL_FALSE;
    2019               0 :                 goto done;
    2020                 :         }
    2021                 : 
    2022               2 :         sqlite_step(res.vm, &ncols, &rowdata, &colnames);
    2023                 : 
    2024               2 :         array_init(return_value);
    2025                 : 
    2026              10 :         for (i = 0; i < ncols; i++) {
    2027               8 :                 if (result_type == PHPSQLITE_ASSOC) {
    2028               8 :                         char *colname = estrdup((char *)colnames[i]);
    2029                 : 
    2030               8 :                         if (SQLITE_G(assoc_case) == 1) {
    2031               0 :                                 php_sqlite_strtoupper(colname);
    2032               8 :                         } else if (SQLITE_G(assoc_case) == 2) {
    2033               0 :                                 php_sqlite_strtolower(colname);
    2034                 :                         }
    2035                 : 
    2036               8 :                         add_assoc_string(return_value, colname, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
    2037               8 :                         efree(colname);
    2038                 :                 }
    2039               8 :                 if (result_type == PHPSQLITE_NUM) {
    2040               0 :                         add_index_string(return_value, i, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
    2041                 :                 }
    2042                 :         }
    2043               2 :         if (res.vm) {
    2044               2 :                 sqlite_finalize(res.vm, NULL);
    2045                 :         }
    2046               2 : done:
    2047               2 :         sqlite_exec(db->db, "PRAGMA show_datatypes = OFF", NULL, NULL, NULL);
    2048                 : }
    2049                 : /* }}} */
    2050                 : 
    2051                 : /* {{{ proto resource sqlite_query(string query, resource db [, int result_type [, string &error_message]])
    2052                 :    Executes a query against a given database and returns a result handle. */
    2053                 : PHP_FUNCTION(sqlite_query)
    2054             219 : {
    2055                 :         zval *zdb;
    2056                 :         struct php_sqlite_db *db;
    2057                 :         char *sql;
    2058                 :         int sql_len;
    2059             219 :         long mode = PHPSQLITE_BOTH;
    2060             219 :         char *errtext = NULL;
    2061             219 :         zval *errmsg = NULL;
    2062             219 :         zval *object = getThis();
    2063                 : 
    2064             219 :         if (object) {
    2065             106 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
    2066               0 :                         return;
    2067                 :                 }
    2068             106 :                 DB_FROM_OBJECT(db, object);
    2069                 :         } else {
    2070             113 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    2071                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
    2072                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
    2073               0 :                         return;
    2074                 :                 }
    2075             113 :                 DB_FROM_ZVAL(db, &zdb);
    2076                 :         }
    2077                 : 
    2078             219 :         if (errmsg) {
    2079               1 :                 zval_dtor(errmsg);
    2080               1 :                 ZVAL_NULL(errmsg);
    2081                 :         }
    2082                 : 
    2083             219 :         PHP_SQLITE_EMPTY_QUERY;
    2084                 : 
    2085                 :         /* avoid doing work if we can */
    2086             219 :         if (!return_value_used) {
    2087             179 :                 db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    2088                 : 
    2089             179 :                 if (db->last_err_code != SQLITE_OK) {
    2090               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    2091               0 :                         if (errmsg) {
    2092               0 :                                 ZVAL_STRING(errmsg, errtext, 1);
    2093                 :                         }
    2094               0 :                         sqlite_freemem(errtext);
    2095                 :                 }
    2096             179 :                 return;
    2097                 :         }
    2098                 : 
    2099              40 :         sqlite_query(object, db, sql, sql_len, (int)mode, 1, return_value, NULL, errmsg TSRMLS_CC);
    2100                 : }
    2101                 : /* }}} */
    2102                 : 
    2103                 : /* {{{ proto boolean sqlite_exec(string query, resource db[, string &error_message])
    2104                 :    Executes a result-less query against a given database */
    2105                 : PHP_FUNCTION(sqlite_exec)
    2106               9 : {
    2107                 :         zval *zdb;
    2108                 :         struct php_sqlite_db *db;
    2109                 :         char *sql;
    2110                 :         int sql_len;
    2111               9 :         char *errtext = NULL;
    2112               9 :         zval *errmsg = NULL;
    2113               9 :         zval *object = getThis();
    2114                 : 
    2115               9 :         if (object) {
    2116               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &sql, &sql_len, &errmsg)) {
    2117               1 :                         return;
    2118                 :                 }
    2119               3 :                 DB_FROM_OBJECT(db, object);
    2120                 :         } else {
    2121               5 :                 if(FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    2122                 :                         ZEND_NUM_ARGS() TSRMLS_CC, "sr", &sql, &sql_len, &zdb) &&
    2123                 :                    FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z/", &zdb, &sql, &sql_len, &errmsg)) {
    2124               1 :                         return;
    2125                 :                 }
    2126               4 :                 DB_FROM_ZVAL(db, &zdb);
    2127                 :         }
    2128                 : 
    2129               7 :         if (errmsg) {
    2130               2 :                 zval_dtor(errmsg);
    2131               2 :                 ZVAL_NULL(errmsg);
    2132                 :         }
    2133                 : 
    2134               7 :         PHP_SQLITE_EMPTY_QUERY;
    2135                 : 
    2136               7 :         db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    2137                 : 
    2138               7 :         if (db->last_err_code != SQLITE_OK) {
    2139               3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    2140               3 :                 if (errmsg) {
    2141               1 :                         ZVAL_STRING(errmsg, errtext, 1);
    2142                 :                 }
    2143               3 :                 sqlite_freemem(errtext);
    2144               3 :                 RETURN_FALSE;
    2145                 :         }
    2146                 : 
    2147               4 :         RETURN_TRUE;
    2148                 : }
    2149                 : /* }}} */
    2150                 : 
    2151                 : /* {{{ php_sqlite_fetch_array */
    2152                 : 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)
    2153             163 : {
    2154             163 :         int j, n = res->ncolumns, buffered = res->buffered;
    2155                 :         const char **rowdata, **colnames;
    2156                 : 
    2157                 :         /* check range of the row */
    2158             163 :         if (res->curr_row >= res->nrows) {
    2159                 :                 /* no more */
    2160              12 :                 RETURN_FALSE;
    2161                 :         }
    2162             151 :         colnames = (const char**)res->col_names;
    2163             151 :         if (res->buffered) {
    2164              98 :                 rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
    2165                 :         } else {
    2166              53 :                 rowdata = (const char**)res->table;
    2167                 :         }
    2168                 : 
    2169                 :         /* now populate the result */
    2170             151 :         array_init(return_value);
    2171                 : 
    2172             352 :         for (j = 0; j < n; j++) {
    2173                 :                 zval *decoded;
    2174             201 :                 MAKE_STD_ZVAL(decoded);
    2175                 : 
    2176             201 :                 if (rowdata[j] == NULL) {
    2177              11 :                         ZVAL_NULL(decoded);
    2178             192 :                 } else if (decode_binary && rowdata[j][0] == '\x01') {
    2179               2 :                         Z_STRVAL_P(decoded) = emalloc(strlen(rowdata[j]));
    2180               2 :                         Z_STRLEN_P(decoded) = php_sqlite_decode_binary(rowdata[j]+1, Z_STRVAL_P(decoded));
    2181               2 :                         Z_STRVAL_P(decoded)[Z_STRLEN_P(decoded)] = '\0';
    2182               2 :                         Z_TYPE_P(decoded) = IS_STRING;
    2183               2 :                         if (!buffered) {
    2184               0 :                                 efree((char*)rowdata[j]);
    2185               0 :                                 rowdata[j] = NULL;
    2186                 :                         }
    2187                 :                 } else {
    2188             188 :                         ZVAL_STRING(decoded, (char*)rowdata[j], buffered);
    2189             188 :                         if (!buffered) {
    2190              70 :                                 rowdata[j] = NULL;
    2191                 :                         }
    2192                 :                 }
    2193                 : 
    2194             201 :                 if (mode & PHPSQLITE_NUM) {
    2195             147 :                         if (mode & PHPSQLITE_ASSOC) {
    2196              15 :                                 add_index_zval(return_value, j, decoded);
    2197              15 :                                 Z_ADDREF_P(decoded);
    2198              15 :                                 add_assoc_zval(return_value, (char*)colnames[j], decoded);
    2199                 :                         } else {
    2200             132 :                                 add_next_index_zval(return_value, decoded);
    2201                 :                         }
    2202                 :                 } else {
    2203              54 :                         add_assoc_zval(return_value, (char*)colnames[j], decoded);
    2204                 :                 }
    2205                 :         }
    2206                 : 
    2207             151 :         if (move_next) {
    2208              89 :                 if (!res->buffered) {
    2209                 :                         /* non buffered: fetch next row */
    2210              33 :                         php_sqlite_fetch(res TSRMLS_CC);
    2211                 :                 }
    2212                 :                 /* advance the row pointer */
    2213              89 :                 res->curr_row++;
    2214                 :         }
    2215                 : }
    2216                 : /* }}} */
    2217                 : 
    2218                 : /* {{{ php_sqlite_fetch_column */
    2219                 : static void php_sqlite_fetch_column(struct php_sqlite_result *res, zval *which, zend_bool decode_binary, zval *return_value TSRMLS_DC)
    2220              38 : {
    2221                 :         int j;
    2222                 :         const char **rowdata, **colnames;
    2223                 : 
    2224                 :         /* check range of the row */
    2225              38 :         if (res->curr_row >= res->nrows) {
    2226                 :                 /* no more */
    2227               0 :                 RETURN_FALSE;
    2228                 :         }
    2229              38 :         colnames = (const char**)res->col_names;
    2230                 : 
    2231              38 :         if (Z_TYPE_P(which) == IS_LONG) {
    2232              22 :                 j = Z_LVAL_P(which);
    2233                 :         } else {
    2234              16 :                 convert_to_string_ex(&which);
    2235              24 :                 for (j = 0; j < res->ncolumns; j++) {
    2236              24 :                         if (!strcasecmp((char*)colnames[j], Z_STRVAL_P(which))) {
    2237              16 :                                 break;
    2238                 :                         }
    2239                 :                 }
    2240                 :         }
    2241              38 :         if (j < 0 || j >= res->ncolumns) {
    2242               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such column %d", j);
    2243               0 :                 RETURN_FALSE;
    2244                 :         }
    2245                 : 
    2246              38 :         if (res->buffered) {
    2247              16 :                 rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
    2248                 :         } else {
    2249              22 :                 rowdata = (const char**)res->table;
    2250                 :         }
    2251                 : 
    2252              38 :         if (rowdata[j] == NULL) {
    2253              11 :                 RETURN_NULL();
    2254              27 :         } else if (decode_binary && rowdata[j] != NULL && rowdata[j][0] == '\x01') {
    2255               0 :                 int l = strlen(rowdata[j]);
    2256               0 :                 char *decoded = emalloc(l);
    2257               0 :                 l = php_sqlite_decode_binary(rowdata[j]+1, decoded);
    2258               0 :                 decoded[l] = '\0';
    2259               0 :                 RETVAL_STRINGL(decoded, l, 0);
    2260               0 :                 if (!res->buffered) {
    2261               0 :                         efree((char*)rowdata[j]);
    2262               0 :                         rowdata[j] = NULL;
    2263                 :                 }
    2264                 :         } else {
    2265              27 :                 RETVAL_STRING((char*)rowdata[j], res->buffered);
    2266              27 :                 if (!res->buffered) {
    2267              11 :                         rowdata[j] = NULL;
    2268                 :                 }
    2269                 :         }
    2270                 : }
    2271                 : /* }}} */
    2272                 : 
    2273                 : /* {{{ proto array sqlite_fetch_all(resource result [, int result_type [, bool decode_binary]])
    2274                 :    Fetches all rows from a result set as an array of arrays. */
    2275                 : PHP_FUNCTION(sqlite_fetch_all)
    2276              10 : {
    2277                 :         zval *zres, *ent;
    2278              10 :         long mode = PHPSQLITE_BOTH;
    2279              10 :         zend_bool decode_binary = 1;
    2280                 :         struct php_sqlite_result *res;
    2281              10 :         zval *object = getThis();
    2282                 : 
    2283              10 :         if (object) {
    2284               5 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
    2285               0 :                         return;
    2286                 :                 }
    2287               5 :                 RES_FROM_OBJECT(res, object);
    2288               5 :                 if (!ZEND_NUM_ARGS()) {
    2289               5 :                         mode = res->mode;
    2290                 :                 }
    2291                 :         } else {
    2292               5 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
    2293               0 :                         return;
    2294                 :                 }
    2295               5 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2296               5 :                 if (ZEND_NUM_ARGS() < 2) {
    2297               5 :                         mode = res->mode;
    2298                 :                 }
    2299                 :         }
    2300                 : 
    2301              10 :         if (res->curr_row >= res->nrows && res->nrows) {
    2302               4 :                 if (!res->buffered) {
    2303               2 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "One or more rowsets were already returned; returning NULL this time");
    2304                 :                 } else {
    2305               2 :                         res->curr_row = 0;
    2306                 :                 }
    2307                 :         }
    2308                 : 
    2309              10 :         array_init(return_value);
    2310                 : 
    2311              42 :         while (res->curr_row < res->nrows) {
    2312              22 :                 MAKE_STD_ZVAL(ent);
    2313              22 :                 php_sqlite_fetch_array(res, mode, decode_binary, 1, ent TSRMLS_CC);
    2314              22 :                 add_next_index_zval(return_value, ent);
    2315                 :         }
    2316                 : }
    2317                 : /* }}} */
    2318                 : 
    2319                 : /* {{{ proto array sqlite_fetch_array(resource result [, int result_type [, bool decode_binary]])
    2320                 :    Fetches the next row from a result set as an array. */
    2321                 : PHP_FUNCTION(sqlite_fetch_array)
    2322              51 : {
    2323                 :         zval *zres;
    2324              51 :         long mode = PHPSQLITE_BOTH;
    2325              51 :         zend_bool decode_binary = 1;
    2326                 :         struct php_sqlite_result *res;
    2327              51 :         zval *object = getThis();
    2328                 : 
    2329              51 :         if (object) {
    2330              15 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
    2331               0 :                         return;
    2332                 :                 }
    2333              15 :                 RES_FROM_OBJECT(res, object);
    2334              15 :                 if (!ZEND_NUM_ARGS()) {
    2335               4 :                         mode = res->mode;
    2336                 :                 }
    2337                 :         } else {
    2338              36 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
    2339               0 :                         return;
    2340                 :                 }
    2341              36 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2342              36 :                 if (ZEND_NUM_ARGS() < 2) {
    2343               4 :                         mode = res->mode;
    2344                 :                 }
    2345                 :         }
    2346                 : 
    2347              51 :         php_sqlite_fetch_array(res, mode, decode_binary, 1, return_value TSRMLS_CC);
    2348                 : }
    2349                 : /* }}} */
    2350                 : 
    2351                 : /* {{{ proto object sqlite_fetch_object(resource result [, string class_name [, NULL|array ctor_params [, bool decode_binary]]])
    2352                 :    Fetches the next row from a result set as an object. */
    2353                 :    /* note that you can do array(&$val) for param ctor_params */
    2354                 : PHP_FUNCTION(sqlite_fetch_object)
    2355              26 : {
    2356                 :         zval *zres;
    2357              26 :         zend_bool decode_binary = 1;
    2358                 :         struct php_sqlite_result *res;
    2359              26 :         zval *object = getThis();
    2360              26 :         char *class_name = NULL;
    2361                 :         int class_name_len;
    2362                 :         zend_class_entry *ce;
    2363                 :         zval dataset;
    2364                 :         zend_fcall_info fci;
    2365                 :         zend_fcall_info_cache fcc;
    2366                 :         zval *retval_ptr;
    2367              26 :         zval *ctor_params = NULL;
    2368                 :         zend_error_handling error_handling;
    2369                 : 
    2370              26 :         zend_replace_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception, &error_handling TSRMLS_CC);
    2371              26 :         if (object) {
    2372              16 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szb", &class_name, &class_name_len, &ctor_params, &decode_binary)) {
    2373               0 :                         zend_restore_error_handling(&error_handling TSRMLS_CC);
    2374               0 :                         return;
    2375                 :                 }
    2376              16 :                 RES_FROM_OBJECT_RESTORE_ERH(res, object, &error_handling);
    2377              16 :                 if (!class_name) {
    2378               3 :                         ce = zend_standard_class_def;
    2379                 :                 } else {
    2380              13 :                         ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
    2381                 :                 }
    2382                 :         } else {
    2383              10 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|szb", &zres, &class_name, &class_name_len, &ctor_params, &decode_binary)) {
    2384               0 :                         zend_restore_error_handling(&error_handling TSRMLS_CC);
    2385               0 :                         return;
    2386                 :                 }
    2387              10 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2388              10 :                 if (!class_name) {
    2389               7 :                         ce = zend_standard_class_def;
    2390                 :                 } else {
    2391               3 :                         ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
    2392                 :                 }
    2393                 :         }
    2394                 : 
    2395              26 :         if (!ce) {
    2396               0 :                 zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Could not find class '%s'", class_name);
    2397               0 :                 zend_restore_error_handling(&error_handling TSRMLS_CC);
    2398               0 :                 return;
    2399                 :         }
    2400                 : 
    2401              26 :         if (res->curr_row < res->nrows) {
    2402              21 :                 php_sqlite_fetch_array(res, PHPSQLITE_ASSOC, decode_binary, 1, &dataset TSRMLS_CC);
    2403                 :         } else {
    2404               5 :                 zend_restore_error_handling(&error_handling TSRMLS_CC);
    2405               5 :                 RETURN_FALSE;
    2406                 :         }
    2407                 : 
    2408              21 :         object_and_properties_init(return_value, ce, NULL);
    2409              21 :         zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
    2410                 : 
    2411              21 :         zend_restore_error_handling(&error_handling TSRMLS_CC);
    2412                 : 
    2413              21 :         if (ce->constructor) {
    2414              12 :                 fci.size = sizeof(fci);
    2415              12 :                 fci.function_table = &ce->function_table;
    2416              12 :                 fci.function_name = NULL;
    2417              12 :                 fci.symbol_table = NULL;
    2418              12 :                 fci.object_ptr = return_value;
    2419              12 :                 fci.retval_ptr_ptr = &retval_ptr;
    2420              18 :                 if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
    2421               6 :                         if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
    2422               6 :                                 HashTable *ht = Z_ARRVAL_P(ctor_params);
    2423                 :                                 Bucket *p;
    2424                 : 
    2425               6 :                                 fci.param_count = 0;
    2426               6 :                                 fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
    2427               6 :                                 p = ht->pListHead;
    2428              18 :                                 while (p != NULL) {
    2429               6 :                                         fci.params[fci.param_count++] = (zval**)p->pData;
    2430               6 :                                         p = p->pListNext;
    2431                 :                                 }
    2432                 :                         } else {
    2433                 :                                 /* Two problems why we throw exceptions here: PHP is typeless
    2434                 :                                  * and hence passing one argument that's not an array could be
    2435                 :                                  * by mistake and the other way round is possible, too. The
    2436                 :                                  * single value is an array. Also we'd have to make that one
    2437                 :                                  * argument passed by reference.
    2438                 :                                  */
    2439               0 :                                 zend_throw_exception(sqlite_ce_exception, "Parameter ctor_params must be an array", 0 TSRMLS_CC);
    2440               0 :                                 return;
    2441                 :                         }
    2442                 :                 } else {
    2443               6 :                         fci.param_count = 0;
    2444               6 :                         fci.params = NULL;
    2445                 :                 }
    2446              12 :                 fci.no_separation = 1;
    2447                 : 
    2448              12 :                 fcc.initialized = 1;
    2449              12 :                 fcc.function_handler = ce->constructor;
    2450              12 :                 fcc.calling_scope = EG(scope);
    2451              12 :                 fcc.called_scope = Z_OBJCE_P(return_value);
    2452              12 :                 fcc.object_ptr = return_value;
    2453                 : 
    2454              12 :                 if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
    2455               0 :                         zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Could not execute %s::%s()", class_name, ce->constructor->common.function_name);
    2456                 :                 } else {
    2457              12 :                         if (retval_ptr) {
    2458              12 :                                 zval_ptr_dtor(&retval_ptr);
    2459                 :                         }
    2460                 :                 }
    2461              12 :                 if (fci.params) {
    2462               6 :                         efree(fci.params);
    2463                 :                 }
    2464               9 :         } else if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
    2465               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);
    2466                 :         }
    2467                 : }
    2468                 : /* }}} */
    2469                 : 
    2470                 : /* {{{ proto array sqlite_array_query(resource db, string query [ , int result_type [, bool decode_binary]])
    2471                 :    Executes a query against a given database and returns an array of arrays. */
    2472                 : PHP_FUNCTION(sqlite_array_query)
    2473               6 : {
    2474                 :         zval *zdb, *ent;
    2475                 :         struct php_sqlite_db *db;
    2476                 :         struct php_sqlite_result *rres;
    2477                 :         char *sql;
    2478                 :         int sql_len;
    2479               6 :         long mode = PHPSQLITE_BOTH;
    2480               6 :         char *errtext = NULL;
    2481               6 :         zend_bool decode_binary = 1;
    2482               6 :         zval *object = getThis();
    2483                 : 
    2484               6 :         if (object) {
    2485               3 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &sql, &sql_len, &mode, &decode_binary)) {
    2486               1 :                         return;
    2487                 :                 }
    2488               2 :                 DB_FROM_OBJECT(db, object);
    2489                 :         } else {
    2490               3 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    2491                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|lb", &sql, &sql_len, &zdb, &mode, &decode_binary) &&
    2492                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zdb, &sql, &sql_len, &mode, &decode_binary)) {
    2493               0 :                         return;
    2494                 :                 }
    2495               3 :                 DB_FROM_ZVAL(db, &zdb);
    2496                 :         }
    2497                 : 
    2498               5 :         PHP_SQLITE_EMPTY_QUERY;
    2499                 : 
    2500                 :         /* avoid doing work if we can */
    2501               3 :         if (!return_value_used) {
    2502               1 :                 db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    2503                 : 
    2504               1 :                 if (db->last_err_code != SQLITE_OK) {
    2505               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    2506               1 :                         sqlite_freemem(errtext);
    2507                 :                 }
    2508               1 :                 return;
    2509                 :         }
    2510                 : 
    2511               2 :         rres = (struct php_sqlite_result *)emalloc(sizeof(*rres));
    2512               2 :         sqlite_query(NULL, db, sql, sql_len, (int)mode, 0, NULL, &rres, NULL TSRMLS_CC);
    2513               2 :         if (db->last_err_code != SQLITE_OK) {
    2514               0 :                 if (rres) {
    2515               0 :                         efree(rres);
    2516                 :                 }
    2517               0 :                 RETURN_FALSE;
    2518                 :         }
    2519                 : 
    2520               2 :         array_init(return_value);
    2521                 : 
    2522              10 :         while (rres->curr_row < rres->nrows) {
    2523               6 :                 MAKE_STD_ZVAL(ent);
    2524               6 :                 php_sqlite_fetch_array(rres, mode, decode_binary, 1, ent TSRMLS_CC);
    2525               6 :                 add_next_index_zval(return_value, ent);
    2526                 :         }
    2527               2 :         real_result_dtor(rres TSRMLS_CC);
    2528                 : }
    2529                 : /* }}} */
    2530                 : 
    2531                 : /* {{{ php_sqlite_fetch_single */
    2532                 : static void php_sqlite_fetch_single(struct php_sqlite_result *res, zend_bool decode_binary, zval *return_value TSRMLS_DC)
    2533              35 : {
    2534                 :         const char **rowdata;
    2535                 :         char *decoded;
    2536                 :         int decoded_len;
    2537                 : 
    2538                 :         /* check range of the row */
    2539              35 :         if (res->curr_row >= res->nrows) {
    2540                 :                 /* no more */
    2541               0 :                 RETURN_FALSE;
    2542                 :         }
    2543                 : 
    2544              35 :         if (res->buffered) {
    2545               4 :                 rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
    2546                 :         } else {
    2547              31 :                 rowdata = (const char**)res->table;
    2548                 :         }
    2549                 : 
    2550              35 :         if (decode_binary && rowdata[0] != NULL && rowdata[0][0] == '\x01') {
    2551               0 :                 decoded = emalloc(strlen(rowdata[0]));
    2552               0 :                 decoded_len = php_sqlite_decode_binary(rowdata[0]+1, decoded);
    2553               0 :                 if (!res->buffered) {
    2554               0 :                         efree((char*)rowdata[0]);
    2555               0 :                         rowdata[0] = NULL;
    2556                 :                 }
    2557              35 :         } else if (rowdata[0]) {
    2558              33 :                 decoded_len = strlen((char*)rowdata[0]);
    2559              33 :                 if (res->buffered) {
    2560               4 :                         decoded = estrndup((char*)rowdata[0], decoded_len);
    2561                 :                 } else {
    2562              29 :                         decoded = (char*)rowdata[0];
    2563              29 :                         rowdata[0] = NULL;
    2564                 :                 }
    2565                 :         } else {
    2566               2 :                 decoded = NULL;
    2567               2 :                 decoded_len = 0;
    2568                 :         }
    2569                 : 
    2570              35 :         if (!res->buffered) {
    2571                 :                 /* non buffered: fetch next row */
    2572              31 :                 php_sqlite_fetch(res TSRMLS_CC);
    2573                 :         }
    2574                 :         /* advance the row pointer */
    2575              35 :         res->curr_row++;
    2576                 : 
    2577              35 :         if (decoded == NULL) {
    2578               2 :                 RETURN_NULL();
    2579                 :         } else {
    2580              33 :                 RETURN_STRINGL(decoded, decoded_len, 0);
    2581                 :         }
    2582                 : }
    2583                 : /* }}} */
    2584                 : 
    2585                 : 
    2586                 : /* {{{ proto array sqlite_single_query(resource db, string query [, bool first_row_only [, bool decode_binary]])
    2587                 :    Executes a query and returns either an array for one single column or the value of the first row. */
    2588                 : PHP_FUNCTION(sqlite_single_query)
    2589              26 : {
    2590                 :         zval *zdb, *ent;
    2591                 :         struct php_sqlite_db *db;
    2592                 :         struct php_sqlite_result *rres;
    2593                 :         char *sql;
    2594                 :         int sql_len;
    2595              26 :         char *errtext = NULL;
    2596              26 :         zend_bool decode_binary = 1;
    2597              26 :         zend_bool srow = 1;
    2598              26 :         zval *object = getThis();
    2599                 : 
    2600              26 :         if (object) {
    2601              19 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb", &sql, &sql_len, &srow, &decode_binary)) {
    2602               0 :                         return;
    2603                 :                 }
    2604              19 :                 RES_FROM_OBJECT(db, object);
    2605                 :         } else {
    2606               7 :                 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
    2607                 :                                 ZEND_NUM_ARGS() TSRMLS_CC, "sr|bb", &sql, &sql_len, &zdb, &srow, &decode_binary) &&
    2608                 :                         FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|bb", &zdb, &sql, &sql_len, &srow, &decode_binary)) {
    2609               0 :                         return;
    2610                 :                 }
    2611               7 :                 DB_FROM_ZVAL(db, &zdb);
    2612                 :         }
    2613                 : 
    2614              26 :         PHP_SQLITE_EMPTY_QUERY;
    2615                 : 
    2616                 :         /* avoid doing work if we can */
    2617              26 :         if (!return_value_used) {
    2618               0 :                 db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
    2619                 : 
    2620               0 :                 if (db->last_err_code != SQLITE_OK) {
    2621               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
    2622               0 :                         sqlite_freemem(errtext);
    2623                 :                 }
    2624               0 :                 return;
    2625                 :         }
    2626                 : 
    2627              26 :         rres = (struct php_sqlite_result *)emalloc(sizeof(*rres));
    2628              26 :         sqlite_query(NULL, db, sql, sql_len, PHPSQLITE_NUM, 0, NULL, &rres, NULL TSRMLS_CC);
    2629              26 :         if (db->last_err_code != SQLITE_OK) {
    2630               3 :                 if (rres) {
    2631               2 :                         efree(rres);
    2632                 :                 }
    2633               3 :                 RETURN_FALSE;
    2634                 :         }
    2635                 : 
    2636              23 :         if (!srow) {
    2637               2 :                 array_init(return_value);
    2638                 :         }
    2639                 : 
    2640              56 :         while (rres->curr_row < rres->nrows) {
    2641              27 :                 MAKE_STD_ZVAL(ent);
    2642              27 :                 php_sqlite_fetch_single(rres, decode_binary, ent TSRMLS_CC);
    2643                 : 
    2644                 :                 /* if set and we only have 1 row in the result set, return the result as a string. */
    2645              27 :                 if (srow) {
    2646              19 :                         if (rres->curr_row == 1 && rres->curr_row >= rres->nrows) {
    2647              17 :                                 *return_value = *ent;
    2648              17 :                                 zval_copy_ctor(return_value);
    2649              17 :                                 zval_dtor(ent);
    2650              17 :                                 FREE_ZVAL(ent);
    2651              17 :                                 break;
    2652                 :                         } else {
    2653               2 :                                 srow = 0;
    2654               2 :                                 array_init(return_value);
    2655                 :                         }
    2656                 :                 }
    2657              10 :                 add_next_index_zval(return_value, ent);
    2658                 :         }
    2659                 : 
    2660              23 :         real_result_dtor(rres TSRMLS_CC);
    2661                 : }
    2662                 : /* }}} */
    2663                 : 
    2664                 : 
    2665                 : /* {{{ proto string sqlite_fetch_single(resource result [, bool decode_binary])
    2666                 :    Fetches the first column of a result set as a string. */
    2667                 : PHP_FUNCTION(sqlite_fetch_single)
    2668               8 : {
    2669                 :         zval *zres;
    2670               8 :         zend_bool decode_binary = 1;
    2671                 :         struct php_sqlite_result *res;
    2672               8 :         zval *object = getThis();
    2673                 : 
    2674               8 :         if (object) {
    2675               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &decode_binary)) {
    2676               0 :                         return;
    2677                 :                 }
    2678               4 :                 RES_FROM_OBJECT(res, object);
    2679                 :         } else {
    2680               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zres, &decode_binary)) {
    2681               0 :                         return;
    2682                 :                 }
    2683               4 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2684                 :         }
    2685                 : 
    2686               8 :         php_sqlite_fetch_single(res, decode_binary, return_value TSRMLS_CC);
    2687                 : }
    2688                 : /* }}} */
    2689                 : 
    2690                 : /* {{{ proto array sqlite_current(resource result [, int result_type [, bool decode_binary]])
    2691                 :    Fetches the current row from a result set as an array. */
    2692                 : PHP_FUNCTION(sqlite_current)
    2693              48 : {
    2694                 :         zval *zres;
    2695              48 :         long mode = PHPSQLITE_BOTH;
    2696              48 :         zend_bool decode_binary = 1;
    2697                 :         struct php_sqlite_result *res;
    2698              48 :         zval *object = getThis();
    2699                 : 
    2700              48 :         if (object) {
    2701              17 :                 if (ZEND_NUM_ARGS() && FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
    2702               0 :                         return;
    2703                 :                 }
    2704              17 :                 RES_FROM_OBJECT(res, object);
    2705              17 :                 if (!ZEND_NUM_ARGS()) {
    2706              13 :                         mode = res->mode;
    2707                 :                 }
    2708                 :         } else {
    2709              31 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
    2710               0 :                         return;
    2711                 :                 }
    2712              31 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2713              31 :                 if (ZEND_NUM_ARGS() < 2) {
    2714              20 :                         mode = res->mode;
    2715                 :                 }
    2716                 :         }
    2717                 : 
    2718              48 :         php_sqlite_fetch_array(res, mode, decode_binary, 0, return_value TSRMLS_CC);
    2719                 : }
    2720                 : /* }}} */
    2721                 : 
    2722                 : /* {{{ proto mixed sqlite_column(resource result, mixed index_or_name [, bool decode_binary])
    2723                 :    Fetches a column from the current row of a result set. */
    2724                 : PHP_FUNCTION(sqlite_column)
    2725              38 : {
    2726                 :         zval *zres;
    2727                 :         zval *which;
    2728              38 :         zend_bool decode_binary = 1;
    2729                 :         struct php_sqlite_result *res;
    2730              38 :         zval *object = getThis();
    2731                 : 
    2732              38 :         if (object) {
    2733              22 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &which, &decode_binary)) {
    2734               0 :                         return;
    2735                 :                 }
    2736              22 :                 RES_FROM_OBJECT(res, object);
    2737                 :         } else {
    2738              16 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zres, &which, &decode_binary)) {
    2739               0 :                         return;
    2740                 :                 }
    2741              16 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2742                 :         }
    2743                 : 
    2744              38 :         php_sqlite_fetch_column(res, which, decode_binary, return_value TSRMLS_CC);
    2745                 : }
    2746                 : /* }}} */
    2747                 : 
    2748                 : /* {{{ proto string sqlite_libversion()
    2749                 :    Returns the version of the linked SQLite library. */
    2750                 : PHP_FUNCTION(sqlite_libversion)
    2751               0 : {
    2752               0 :         if (zend_parse_parameters_none() == FAILURE) {
    2753               0 :                 return;
    2754                 :         }
    2755               0 :         RETURN_STRING((char*)sqlite_libversion(), 1);
    2756                 : }
    2757                 : /* }}} */
    2758                 : 
    2759                 : /* {{{ proto string sqlite_libencoding()
    2760                 :    Returns the encoding (iso8859 or UTF-8) of the linked SQLite library. */
    2761                 : PHP_FUNCTION(sqlite_libencoding)
    2762               0 : {
    2763               0 :         if (zend_parse_parameters_none() == FAILURE) {
    2764               0 :                 return;
    2765                 :         }
    2766               0 :         RETURN_STRING((char*)sqlite_libencoding(), 1);
    2767                 : }
    2768                 : /* }}} */
    2769                 : 
    2770                 : /* {{{ proto int sqlite_changes(resource db)
    2771                 :    Returns the number of rows that were changed by the most recent SQL statement. */
    2772                 : PHP_FUNCTION(sqlite_changes)
    2773               6 : {
    2774                 :         zval *zdb;
    2775                 :         struct php_sqlite_db *db;
    2776               6 :         zval *object = getThis();
    2777                 : 
    2778               6 :         if (object) {
    2779               6 :                 if (zend_parse_parameters_none() == FAILURE) {
    2780               0 :                         return;
    2781                 :                 }
    2782               6 :                 DB_FROM_OBJECT(db, object);
    2783                 :         } else {
    2784               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
    2785               0 :                         return;
    2786                 :                 }
    2787               0 :                 DB_FROM_ZVAL(db, &zdb);
    2788                 :         }
    2789                 : 
    2790               6 :         RETURN_LONG(sqlite_changes(db->db));
    2791                 : }
    2792                 : /* }}} */
    2793                 : 
    2794                 : /* {{{ proto int sqlite_last_insert_rowid(resource db)
    2795                 :    Returns the rowid of the most recently inserted row. */
    2796                 : PHP_FUNCTION(sqlite_last_insert_rowid)
    2797               0 : {
    2798                 :         zval *zdb;
    2799                 :         struct php_sqlite_db *db;
    2800               0 :         zval *object = getThis();
    2801                 : 
    2802               0 :         if (object) {
    2803               0 :                 if (zend_parse_parameters_none() == FAILURE) {
    2804               0 :                         return;
    2805                 :                 }
    2806               0 :                 DB_FROM_OBJECT(db, object);
    2807                 :         } else {
    2808               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
    2809               0 :                         return;
    2810                 :                 }
    2811               0 :                 DB_FROM_ZVAL(db, &zdb);
    2812                 :         }
    2813                 : 
    2814               0 :         RETURN_LONG(sqlite_last_insert_rowid(db->db));
    2815                 : }
    2816                 : /* }}} */
    2817                 : 
    2818                 : static int sqlite_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
    2819               1 : {
    2820               1 :         sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC);
    2821                 : 
    2822               1 :         if (obj->u.res == NULL) {
    2823               1 :                 zend_throw_exception(sqlite_ce_exception, "Row count is not available for this query", 0 TSRMLS_CC);
    2824               1 :                 return FAILURE;
    2825                 :         }
    2826                 : 
    2827               0 :         if (obj->u.res->buffered) {
    2828               0 :                 * count = obj->u.res->nrows;
    2829               0 :                 return SUCCESS;
    2830                 :         } else {
    2831               0 :                 zend_throw_exception(sqlite_ce_exception, "Row count is not available for unbuffered queries", 0 TSRMLS_CC);
    2832               0 :                 return FAILURE;
    2833                 :         }
    2834                 : } /* }}} */
    2835                 : 
    2836                 : /* {{{ proto int sqlite_num_rows(resource result)
    2837                 :    Returns the number of rows in a buffered result set. */
    2838                 : PHP_FUNCTION(sqlite_num_rows)
    2839               2 : {
    2840                 :         zval *zres;
    2841                 :         struct php_sqlite_result *res;
    2842               2 :         zval *object = getThis();
    2843                 : 
    2844               2 :         if (object) {
    2845               2 :                 if (zend_parse_parameters_none() == FAILURE) {
    2846               0 :                         return;
    2847                 :                 }
    2848               2 :                 RES_FROM_OBJECT(res, object);
    2849                 :         } else {
    2850               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2851               0 :                         return;
    2852                 :                 }
    2853               0 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2854                 :         }
    2855                 : 
    2856               2 :         if (res->buffered) {
    2857               2 :                 RETURN_LONG(res->nrows);
    2858                 :         } else {
    2859               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Row count is not available for unbuffered queries");
    2860               0 :                 RETURN_FALSE;
    2861                 :         }
    2862                 : }
    2863                 : /* }}} */
    2864                 : 
    2865                 : /* {{{ proto bool sqlite_valid(resource result)
    2866                 :    Returns whether more rows are available. */
    2867                 : PHP_FUNCTION(sqlite_valid)
    2868              71 : {
    2869                 :         zval *zres;
    2870                 :         struct php_sqlite_result *res;
    2871              71 :         zval *object = getThis();
    2872                 : 
    2873              71 :         if (object) {
    2874              31 :                 if (zend_parse_parameters_none() == FAILURE) {
    2875               0 :                         return;
    2876                 :                 }
    2877              31 :                 RES_FROM_OBJECT(res, object);
    2878                 :         } else {
    2879              40 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2880               0 :                         return;
    2881                 :                 }
    2882              40 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2883                 :         }
    2884                 : 
    2885              71 :         RETURN_BOOL(res->curr_row < res->nrows && res->nrows); /* curr_row may be -1 */
    2886                 : }
    2887                 : /* }}} */
    2888                 : 
    2889                 : /* {{{ proto bool sqlite_has_prev(resource result)
    2890                 :  * Returns whether a previous row is available. */
    2891                 : PHP_FUNCTION(sqlite_has_prev)
    2892               4 : {
    2893                 :         zval *zres;
    2894                 :         struct php_sqlite_result *res;
    2895               4 :         zval *object = getThis();
    2896                 : 
    2897               4 :         if (object) {
    2898               0 :                 if (zend_parse_parameters_none() == FAILURE) {
    2899               0 :                         return;
    2900                 :                 }
    2901               0 :                 RES_FROM_OBJECT(res, object);
    2902                 :         } else {
    2903               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2904               0 :                         return;
    2905                 :                 }
    2906               4 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2907                 :         }
    2908                 : 
    2909               4 :         if(!res->buffered) {
    2910               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "you cannot use sqlite_has_prev on unbuffered querys");
    2911               1 :                 RETURN_FALSE;
    2912                 :         }
    2913                 : 
    2914               3 :         RETURN_BOOL(res->curr_row);
    2915                 : }
    2916                 : /* }}} */
    2917                 : 
    2918                 : /* {{{ proto int sqlite_num_fields(resource result)
    2919                 :    Returns the number of fields in a result set. */
    2920                 : PHP_FUNCTION(sqlite_num_fields)
    2921              16 : {
    2922                 :         zval *zres;
    2923                 :         struct php_sqlite_result *res;
    2924              16 :         zval *object = getThis();
    2925                 : 
    2926              16 :         if (object) {
    2927               8 :                 if (zend_parse_parameters_none() == FAILURE) {
    2928               0 :                         return;
    2929                 :                 }
    2930               8 :                 RES_FROM_OBJECT(res, object);
    2931                 :         } else {
    2932               8 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    2933               0 :                         return;
    2934                 :                 }
    2935               8 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2936                 :         }
    2937                 : 
    2938              16 :         RETURN_LONG(res->ncolumns);
    2939                 : }
    2940                 : /* }}} */
    2941                 : 
    2942                 : /* {{{ proto string sqlite_field_name(resource result, int field_index)
    2943                 :    Returns the name of a particular field of a result set. */
    2944                 : PHP_FUNCTION(sqlite_field_name)
    2945              12 : {
    2946                 :         zval *zres;
    2947                 :         struct php_sqlite_result *res;
    2948                 :         long field;
    2949              12 :         zval *object = getThis();
    2950                 : 
    2951              12 :         if (object) {
    2952               6 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &field)) {
    2953               0 :                         return;
    2954                 :                 }
    2955               6 :                 RES_FROM_OBJECT(res, object);
    2956                 :         } else {
    2957               6 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &field)) {
    2958               0 :                         return;
    2959                 :                 }
    2960               6 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2961                 :         }
    2962                 : 
    2963              12 :         if (field < 0 || field >= res->ncolumns) {
    2964               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %ld out of range", field);
    2965               0 :                 RETURN_FALSE;
    2966                 :         }
    2967                 : 
    2968              12 :         RETURN_STRING(res->col_names[field], 1);
    2969                 : }
    2970                 : /* }}} */
    2971                 : 
    2972                 : /* {{{ proto bool sqlite_seek(resource result, int row)
    2973                 :    Seek to a particular row number of a buffered result set. */
    2974                 : PHP_FUNCTION(sqlite_seek)
    2975              20 : {
    2976                 :         zval *zres;
    2977                 :         struct php_sqlite_result *res;
    2978                 :         long row;
    2979              20 :         zval *object = getThis();
    2980                 : 
    2981              20 :         if (object) {
    2982              10 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &row)) {
    2983               0 :                         return;
    2984                 :                 }
    2985              10 :                 RES_FROM_OBJECT(res, object);
    2986                 :         } else {
    2987              10 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &row)) {
    2988               0 :                         return;
    2989                 :                 }
    2990              10 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    2991                 :         }
    2992                 : 
    2993              20 :         if (!res->buffered) {
    2994               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set");
    2995               0 :                 RETURN_FALSE;
    2996                 :         }
    2997                 : 
    2998              20 :         if (row < 0 || row >= res->nrows) {
    2999               8 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "row %ld out of range", row);
    3000               8 :                 RETURN_FALSE;
    3001                 :         }
    3002                 : 
    3003              12 :         res->curr_row = row;
    3004              12 :         RETURN_TRUE;
    3005                 : }
    3006                 : /* }}} */
    3007                 : 
    3008                 : /* {{{ proto bool sqlite_rewind(resource result)
    3009                 :    Seek to the first row number of a buffered result set. */
    3010                 : PHP_FUNCTION(sqlite_rewind)
    3011               3 : {
    3012                 :         zval *zres;
    3013                 :         struct php_sqlite_result *res;
    3014               3 :         zval *object = getThis();
    3015                 : 
    3016               3 :         if (object) {
    3017               0 :                 if (zend_parse_parameters_none() == FAILURE) {
    3018               0 :                         return;
    3019                 :                 }
    3020               0 :                 RES_FROM_OBJECT(res, object);
    3021                 :         } else {
    3022               3 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    3023               0 :                         return;
    3024                 :                 }
    3025               3 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    3026                 :         }
    3027                 : 
    3028               3 :         if (!res->buffered) {
    3029               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot rewind an unbuffered result set");
    3030               1 :                 RETURN_FALSE;
    3031                 :         }
    3032                 : 
    3033               2 :         if (!res->nrows) {
    3034               0 :                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "no rows received");
    3035               0 :                 RETURN_FALSE;
    3036                 :         }
    3037                 : 
    3038               2 :         res->curr_row = 0;
    3039               2 :         RETURN_TRUE;
    3040                 : }
    3041                 : /* }}} */
    3042                 : 
    3043                 : /* {{{ proto bool sqlite_next(resource result)
    3044                 :    Seek to the next row number of a result set. */
    3045                 : PHP_FUNCTION(sqlite_next)
    3046              31 : {
    3047                 :         zval *zres;
    3048                 :         struct php_sqlite_result *res;
    3049              31 :         zval *object = getThis();
    3050                 : 
    3051              31 :         if (object) {
    3052              12 :                 if (zend_parse_parameters_none() == FAILURE) {
    3053               0 :                         return;
    3054                 :                 }
    3055              12 :                 RES_FROM_OBJECT(res, object);
    3056                 :         } else {
    3057              19 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    3058               0 :                         return;
    3059                 :                 }
    3060              19 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    3061                 :         }
    3062                 : 
    3063              31 :         if (!res->buffered && res->vm) {
    3064              18 :                 php_sqlite_fetch(res TSRMLS_CC);
    3065                 :         }
    3066                 : 
    3067              31 :         if (res->curr_row >= res->nrows) {
    3068               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no more rows available");
    3069               0 :                 RETURN_FALSE;
    3070                 :         }
    3071                 : 
    3072              31 :         res->curr_row++;
    3073                 : 
    3074              31 :         RETURN_TRUE;
    3075                 : }
    3076                 : /* }}} */
    3077                 : 
    3078                 : /* {{{ proto int sqlite_key(resource result)
    3079                 :    Return the current row index of a buffered result. */
    3080                 : PHP_FUNCTION(sqlite_key)
    3081               0 : {
    3082                 :         zval *zres;
    3083                 :         struct php_sqlite_result *res;
    3084               0 :         zval *object = getThis();
    3085                 : 
    3086               0 :         if (object) {
    3087               0 :                 if (zend_parse_parameters_none() == FAILURE) {
    3088               0 :                         return;
    3089                 :                 }
    3090               0 :                 RES_FROM_OBJECT(res, object);
    3091                 :         } else {
    3092               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    3093               0 :                         return;
    3094                 :                 }
    3095               0 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    3096                 :         }
    3097                 : 
    3098               0 :         RETURN_LONG(res->curr_row);
    3099                 : }
    3100                 : /* }}} */
    3101                 : 
    3102                 : /* {{{ proto bool sqlite_prev(resource result)
    3103                 :  * Seek to the previous row number of a result set. */
    3104                 : PHP_FUNCTION(sqlite_prev)
    3105               4 : {
    3106                 :         zval *zres;
    3107                 :         struct php_sqlite_result *res;
    3108               4 :         zval *object = getThis();
    3109                 : 
    3110               4 :         if (object) {
    3111               0 :                 if (zend_parse_parameters_none() == FAILURE) {
    3112               0 :                         return;
    3113                 :                 }
    3114               0 :                 RES_FROM_OBJECT(res, object);
    3115                 :         } else {
    3116               4 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
    3117               0 :                         return;
    3118                 :                 }
    3119               4 :                 ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
    3120                 :         }
    3121                 : 
    3122               4 :         if (!res->buffered) {
    3123               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "you cannot use sqlite_prev on unbuffered querys");
    3124               1 :                 RETURN_FALSE;
    3125                 :         }
    3126                 : 
    3127               3 :         if (res->curr_row <= 0) {
    3128               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no previous row available");
    3129               0 :                 RETURN_FALSE;
    3130                 :         }
    3131                 : 
    3132               3 :         res->curr_row--;
    3133                 : 
    3134               3 :         RETURN_TRUE;
    3135                 : }
    3136                 : /* }}} */
    3137                 : 
    3138                 : /* {{{ proto string sqlite_escape_string(string item)
    3139                 :    Escapes a string for use as a query parameter. */
    3140                 : PHP_FUNCTION(sqlite_escape_string)
    3141              24 : {
    3142              24 :         char *string = NULL;
    3143                 :         int stringlen;
    3144                 :         char *ret;
    3145                 : 
    3146              24 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &stringlen)) {
    3147               0 :                 return;
    3148                 :         }
    3149                 : 
    3150              27 :         if (stringlen && (string[0] == '\x01' || memchr(string, '\0', stringlen) != NULL)) {
    3151                 :                 /* binary string */
    3152                 :                 int enclen;
    3153                 : 
    3154               3 :                 ret = safe_emalloc(1 + stringlen / 254, 257, 3);
    3155               3 :                 ret[0] = '\x01';
    3156               3 :                 enclen = php_sqlite_encode_binary(string, stringlen, ret+1);
    3157               3 :                 RETVAL_STRINGL(ret, enclen+1, 0);
    3158                 : 
    3159              21 :         } else if (stringlen) {
    3160              20 :                 ret = sqlite_mprintf("%q", string);
    3161              20 :                 if (ret) {
    3162              20 :                         RETVAL_STRING(ret, 1);
    3163              20 :                         sqlite_freemem(ret);
    3164                 :                 }
    3165                 :         } else {
    3166               1 :                 RETURN_EMPTY_STRING();
    3167                 :         }
    3168                 : }
    3169                 : /* }}} */
    3170                 : 
    3171                 : /* {{{ proto int sqlite_last_error(resource db)
    3172                 :    Returns the error code of the last error for a database. */
    3173                 : PHP_FUNCTION(sqlite_last_error)
    3174               8 : {
    3175                 :         zval *zdb;
    3176                 :         struct php_sqlite_db *db;
    3177               8 :         zval *object = getThis();
    3178                 : 
    3179               8 :         if (object) {
    3180               3 :                 if (zend_parse_parameters_none() == FAILURE) {
    3181               1 :                         return;
    3182                 :                 }
    3183               2 :                 DB_FROM_OBJECT(db, object);
    3184                 :         } else {
    3185               5 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
    3186               2 :                         return;
    3187                 :                 }
    3188               3 :                 DB_FROM_ZVAL(db, &zdb);
    3189                 :         }
    3190                 : 
    3191               5 :         RETURN_LONG(db->last_err_code);
    3192                 : }
    3193                 : /* }}} */
    3194                 : 
    3195                 : /* {{{ proto string sqlite_error_string(int error_code)
    3196                 :    Returns the textual description of an error code. */
    3197                 : PHP_FUNCTION(sqlite_error_string)
    3198               0 : {
    3199                 :         long code;
    3200                 :         const char *msg;
    3201                 : 
    3202               0 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
    3203               0 :                 return;
    3204                 :         }
    3205                 : 
    3206               0 :         msg = sqlite_error_string(code);
    3207                 : 
    3208               0 :         if (msg) {
    3209               0 :                 RETURN_STRING((char*)msg, 1);
    3210                 :         } else {
    3211               0 :                 RETURN_NULL();
    3212                 :         }
    3213                 : }
    3214                 : /* }}} */
    3215                 : 
    3216                 : /* manages duplicate registrations of a particular function, and
    3217                 :  * also handles the case where the db is using a persistent connection */
    3218                 : enum callback_prep_t { DO_REG, SKIP_REG, ERR };
    3219                 : 
    3220                 : static enum callback_prep_t prep_callback_struct(struct php_sqlite_db *db, int is_agg,
    3221                 :                 char *funcname,
    3222                 :                 zval *step, zval *fini, struct php_sqlite_agg_functions **funcs)
    3223               5 : {
    3224                 :         struct php_sqlite_agg_functions *alloc_funcs, func_tmp;
    3225                 :         char *hashkey;
    3226                 :         int hashkeylen;
    3227                 :         enum callback_prep_t ret;
    3228                 : 
    3229               5 :         hashkeylen = spprintf(&hashkey, 0, "%s-%s", is_agg ? "agg" : "reg", funcname);
    3230                 : 
    3231                 :         /* is it already registered ? */
    3232               5 :         if (SUCCESS == zend_hash_find(&db->callbacks, hashkey, hashkeylen+1, (void*)&alloc_funcs)) {
    3233                 :                 /* override the previous definition */
    3234                 : 
    3235               0 :                 if (alloc_funcs->is_valid) {
    3236                 :                         /* release these */
    3237                 : 
    3238               0 :                         if (alloc_funcs->step) {
    3239               0 :                                 zval_ptr_dtor(&alloc_funcs->step);
    3240               0 :                                 alloc_funcs->step = NULL;
    3241                 :                         }
    3242                 : 
    3243               0 :                         if (alloc_funcs->fini) {
    3244               0 :                                 zval_ptr_dtor(&alloc_funcs->fini);
    3245               0 :                                 alloc_funcs->fini = NULL;
    3246                 :                         }
    3247                 :                 }
    3248                 : 
    3249               0 :                 ret = SKIP_REG;
    3250                 :         } else {
    3251                 :                 /* add a new one */
    3252               5 :                 func_tmp.db = db;
    3253                 : 
    3254               5 :                 ret = SUCCESS == zend_hash_update(&db->callbacks, hashkey, hashkeylen+1,
    3255                 :                                 (void*)&func_tmp, sizeof(func_tmp), (void**)&alloc_funcs) ? DO_REG : ERR;
    3256                 :         }
    3257                 : 
    3258               5 :         efree(hashkey);
    3259                 : 
    3260               5 :         MAKE_STD_ZVAL(alloc_funcs->step);
    3261               5 :         *(alloc_funcs->step)  = *step;
    3262               5 :         zval_copy_ctor(alloc_funcs->step);
    3263               5 :         INIT_PZVAL(alloc_funcs->step);
    3264                 : 
    3265               5 :         if (is_agg) {
    3266               2 :                 MAKE_STD_ZVAL(alloc_funcs->fini);
    3267               2 :                 *(alloc_funcs->fini) = *fini;
    3268               2 :                 zval_copy_ctor(alloc_funcs->fini);
    3269               2 :                 INIT_PZVAL(alloc_funcs->fini);
    3270                 :         } else {
    3271               3 :                 alloc_funcs->fini = NULL;
    3272                 :         }
    3273               5 :         alloc_funcs->is_valid = 1;
    3274               5 :         *funcs = alloc_funcs;
    3275                 : 
    3276               5 :         return ret;
    3277                 : }
    3278                 : 
    3279                 : 
    3280                 : /* {{{ proto bool sqlite_create_aggregate(resource db, string funcname, mixed step_func, mixed finalize_func[, long num_args])
    3281                 :     Registers an aggregate function for queries. */
    3282                 : PHP_FUNCTION(sqlite_create_aggregate)
    3283               2 : {
    3284               2 :         char *funcname = NULL;
    3285                 :         int funcname_len;
    3286                 :         zval *zstep, *zfinal, *zdb;
    3287                 :         struct php_sqlite_db *db;
    3288                 :         struct php_sqlite_agg_functions *funcs;
    3289               2 :         char *callable = NULL;
    3290               2 :         long num_args = -1;
    3291               2 :         zval *object = getThis();
    3292                 : 
    3293               2 :         if (object) {
    3294               0 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
    3295               0 :                         return;
    3296                 :                 }
    3297               0 :                 DB_FROM_OBJECT(db, object);
    3298                 :         } else {
    3299               2 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rszz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
    3300               0 :                         return;
    3301                 :                 }
    3302               2 :                 DB_FROM_ZVAL(db, &zdb);
    3303                 :         }
    3304                 : 
    3305               2 :         if (!zend_is_callable(zstep, 0, &callable TSRMLS_CC)) {
    3306               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "step function `%s' is not callable", callable);
    3307               0 :                 efree(callable);
    3308               0 :                 return;
    3309                 :         }
    3310               2 :         efree(callable);
    3311                 : 
    3312               2 :         if (!zend_is_callable(zfinal, 0, &callable TSRMLS_CC)) {
    3313               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "finalize function `%s' is not callable", callable);
    3314               0 :                 efree(callable);
    3315               0 :                 return;
    3316                 :         }
    3317               2 :         efree(callable);
    3318                 : 
    3319                 : 
    3320               2 :         if (prep_callback_struct(db, 1, funcname, zstep, zfinal, &funcs) == DO_REG) {
    3321               2 :                 sqlite_create_aggregate(db->db, funcname, num_args,
    3322                 :                                 php_sqlite_agg_step_function_callback,
    3323                 :                                 php_sqlite_agg_fini_function_callback, funcs);
    3324                 :         }
    3325                 : 
    3326                 : 
    3327                 : }
    3328                 : /* }}} */
    3329                 : 
    3330                 : /* {{{ proto bool sqlite_create_function(resource db, string funcname, mixed callback[, long num_args])
    3331                 :     Registers a "regular" function for queries. */
    3332                 : PHP_FUNCTION(sqlite_create_function)
    3333               3 : {
    3334               3 :         char *funcname = NULL;
    3335                 :         int funcname_len;
    3336                 :         zval *zcall, *zdb;
    3337                 :         struct php_sqlite_db *db;
    3338                 :         struct php_sqlite_agg_functions *funcs;
    3339               3 :         char *callable = NULL;
    3340               3 :         long num_args = -1;
    3341                 : 
    3342               3 :         zval *object = getThis();
    3343                 : 
    3344               3 :         if (object) {
    3345               1 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &funcname, &funcname_len, &zcall, &num_args)) {
    3346               0 :                         return;
    3347                 :                 }
    3348               1 :                 DB_FROM_OBJECT(db, object);
    3349                 :         } else {
    3350               2 :                 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) {
    3351               0 :                         return;
    3352                 :                 }
    3353               2 :                 DB_FROM_ZVAL(db, &zdb);
    3354                 :         }
    3355                 : 
    3356               3 :         if (!zend_is_callable(zcall, 0, &callable TSRMLS_CC)) {
    3357               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function `%s' is not callable", callable);
    3358               0 :                 efree(callable);
    3359               0 :                 return;
    3360                 :         }
    3361               3 :         efree(callable);
    3362                 : 
    3363               3 :         if (prep_callback_struct(db, 0, funcname, zcall, NULL, &funcs) == DO_REG) {
    3364               3 :                 sqlite_create_function(db->db, funcname, num_args, php_sqlite_function_callback, funcs);
    3365                 :         }
    3366                 : }
    3367                 : /* }}} */
    3368                 : 
    3369                 : /* {{{ proto string sqlite_udf_encode_binary(string data)
    3370                 :    Apply binary encoding (if required) to a string to return from an UDF. */
    3371                 : PHP_FUNCTION(sqlite_udf_encode_binary)
    3372               5 : {
    3373               5 :         char *data = NULL;
    3374                 :         int datalen;
    3375                 : 
    3376               5 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
    3377               0 :                 return;
    3378                 :         }
    3379                 : 
    3380               5 :         if (data == NULL) {
    3381               0 :                 RETURN_NULL();
    3382                 :         }
    3383               8 :         if (datalen && (data[0] == '\x01' || memchr(data, '\0', datalen) != NULL)) {
    3384                 :                 /* binary string */
    3385                 :                 int enclen;
    3386                 :                 char *ret;
    3387                 : 
    3388               3 :                 ret = safe_emalloc(1 + datalen / 254, 257, 3);
    3389               3 :                 ret[0] = '\x01';
    3390               3 :                 enclen = php_sqlite_encode_binary(data, datalen, ret+1);
    3391               3 :                 RETVAL_STRINGL(ret, enclen+1, 0);
    3392                 :         } else {
    3393               2 :                 RETVAL_STRINGL(data, datalen, 1);
    3394                 :         }
    3395                 : }
    3396                 : /* }}} */
    3397                 : 
    3398                 : /* {{{ proto string sqlite_udf_decode_binary(string data)
    3399                 :    Decode binary encoding on a string parameter passed to an UDF. */
    3400                 : PHP_FUNCTION(sqlite_udf_decode_binary)
    3401               4 : {
    3402               4 :         char *data = NULL;
    3403                 :         int datalen;
    3404                 : 
    3405               4 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
    3406               0 :                 return;
    3407                 :         }
    3408                 : 
    3409               4 :         if (data == NULL) {
    3410               0 :                 RETURN_NULL();
    3411                 :         }
    3412               6 :         if (datalen && data[0] == '\x01') {
    3413                 :                 /* encoded string */
    3414                 :                 int enclen;
    3415                 :                 char *ret;
    3416                 : 
    3417               2 :                 ret = emalloc(datalen);
    3418               2 :                 enclen = php_sqlite_decode_binary(data+1, ret);
    3419               2 :                 ret[enclen] = '\0';
    3420               2 :                 RETVAL_STRINGL(ret, enclen, 0);
    3421                 :         } else {
    3422               2 :                 RETVAL_STRINGL(data, datalen, 1);
    3423                 :         }
    3424                 : }
    3425                 : /* }}} */
    3426                 : 
    3427                 : 
    3428                 : /*
    3429                 :  * Local variables:
    3430                 :  * tab-width: 4
    3431                 :  * c-basic-offset: 4
    3432                 :  * End:
    3433                 :  * vim600: sw=4 ts=4 fdm=marker
    3434                 :  * vim<600: sw=4 ts=4
    3435                 :  */

Generated by: LTP GCOV extension version 1.5

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

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