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