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