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