From f2d26fc85d4f665415a049f4b591a4f04f011ee5 Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Sun, 22 Jun 2003 17:19:46 +0000 Subject: [PATCH] Add oo API --- ext/sqlite/php_sqlite.h | 4 +- ext/sqlite/sqlite.c | 752 ++++++++++++++++++++++----- ext/sqlite/tests/blankdb_oo.inc | 13 + ext/sqlite/tests/sqlite_oo_001.phpt | 17 + ext/sqlite/tests/sqlite_oo_002.phpt | 41 ++ ext/sqlite/tests/sqlite_oo_003.phpt | 51 ++ ext/sqlite/tests/sqlite_oo_008.phpt | 43 ++ ext/sqlite/tests/sqlite_oo_009.phpt | 43 ++ ext/sqlite/tests/sqlite_oo_010.phpt | 44 ++ ext/sqlite/tests/sqlite_oo_011.phpt | 27 + ext/sqlite/tests/sqlite_oo_012.phpt | 35 ++ ext/sqlite/tests/sqlite_oo_013.phpt | 75 +++ ext/sqlite/tests/sqlite_oo_014.phpt | 118 +++++ ext/sqlite/tests/sqlite_oo_015.phpt | 47 ++ ext/sqlite/tests/sqlite_oo_016.phpt | 42 ++ ext/sqlite/tests/sqlite_oo_020.phpt | 63 +++ ext/sqlite/tests/sqlite_spl_001.phpt | 114 ++++ 17 files changed, 1405 insertions(+), 124 deletions(-) create mode 100755 ext/sqlite/tests/blankdb_oo.inc create mode 100755 ext/sqlite/tests/sqlite_oo_001.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_002.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_003.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_008.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_009.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_010.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_011.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_012.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_013.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_014.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_015.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_016.phpt create mode 100755 ext/sqlite/tests/sqlite_oo_020.phpt create mode 100755 ext/sqlite/tests/sqlite_spl_001.phpt diff --git a/ext/sqlite/php_sqlite.h b/ext/sqlite/php_sqlite.h index 3f937e4656..ea1aa45389 100644 --- a/ext/sqlite/php_sqlite.h +++ b/ext/sqlite/php_sqlite.h @@ -81,8 +81,10 @@ PHP_FUNCTION(sqlite_create_function); PHP_FUNCTION(sqlite_udf_decode_binary); PHP_FUNCTION(sqlite_udf_encode_binary); +PHP_FUNCTION(sqlite_factory); + ZEND_BEGIN_MODULE_GLOBALS(sqlite) - long assoc_case; + int assoc_case; ZEND_END_MODULE_GLOBALS(sqlite) #ifdef ZTS diff --git a/ext/sqlite/sqlite.c b/ext/sqlite/sqlite.c index fdc8abf909..e7b15a8c93 100644 --- a/ext/sqlite/sqlite.c +++ b/ext/sqlite/sqlite.c @@ -24,7 +24,7 @@ #include "config.h" #endif -#define PHP_SQLITE_MODULE_VERSION "1.0" +#define PHP_SQLITE_MODULE_VERSION "1.1-dev" #include "php.h" #include "php_ini.h" @@ -38,6 +38,13 @@ #include +#ifdef HAVE_SPL +#include "ext/spl/php_spl.h" +#include "ext/spl/spl_functions.h" +#endif + +#include "Zend/zend_default_classes.h" + #ifndef safe_emalloc # define safe_emalloc(a,b,c) emalloc((a)*(b)+(c)) #endif @@ -81,6 +88,42 @@ PHP_INI_END() #define DB_FROM_ZVAL(db, zv) ZEND_FETCH_RESOURCE2(db, struct php_sqlite_db *, zv, -1, "sqlite database", le_sqlite_db, le_sqlite_pdb) +#define DB_FROM_OBJECT(db, object) \ + { \ + sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \ + db = obj->u.db; \ + if (!db) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The database wasn't opened"); \ + RETURN_NULL(); \ + } \ + } + +#define RES_FROM_OBJECT(res, object) \ + { \ + sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \ + res = obj->u.res; \ + if (!res) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No result set available"); \ + RETURN_NULL(); \ + } \ + } + +#define SQLITE_THROW(message) \ + PG(suppress_errors) = 0; \ + EG(exception) = sqlite_instanciate(sqlite_ce_exception, NULL TSRMLS_CC); \ + { \ + zval *tmp; \ + MAKE_STD_ZVAL(tmp); \ + ZVAL_STRING(tmp, message, 1); \ + zend_hash_update(Z_OBJPROP_P(EG(exception)), "message", sizeof("message"), (void **) message, sizeof(zval *), NULL); \ + MAKE_STD_ZVAL(tmp); \ + ZVAL_STRING(tmp, zend_get_executed_filename(TSRMLS_C), 1); \ + zend_hash_update(Z_OBJPROP_P(EG(exception)), "file", sizeof("file"), (void **) &tmp, sizeof(zval *), NULL); \ + MAKE_STD_ZVAL(tmp); \ + ZVAL_LONG(tmp, zend_get_executed_lineno(TSRMLS_C)); \ + zend_hash_update(Z_OBJPROP_P(EG(exception)), "line", sizeof("line"), (void **) &tmp, sizeof(zval *), NULL); \ + } + struct php_sqlite_result { struct php_sqlite_db *db; sqlite_vm *vm; @@ -142,11 +185,69 @@ function_entry sqlite_functions[] = { PHP_FE(sqlite_unbuffered_query, NULL) PHP_FE(sqlite_create_aggregate, NULL) PHP_FE(sqlite_create_function, NULL) + PHP_FE(sqlite_factory, NULL) PHP_FE(sqlite_udf_encode_binary, NULL) PHP_FE(sqlite_udf_decode_binary, NULL) {NULL, NULL, NULL} }; +#define PHP_ME_MAPPING(name, func_name, arg_types) \ + ZEND_NAMED_FE(name, ZEND_FN(func_name), arg_types) + +function_entry sqlite_funcs_db[] = { + PHP_ME_MAPPING(sqlite_db, sqlite_open, NULL) + PHP_ME_MAPPING(close, sqlite_close, NULL) + PHP_ME_MAPPING(query, sqlite_query, NULL) + PHP_ME_MAPPING(array_query, sqlite_array_query, NULL) + PHP_ME_MAPPING(unbuffered_query, sqlite_unbuffered_query, NULL) + PHP_ME_MAPPING(last_insert_rowid, sqlite_last_insert_rowid, NULL) + PHP_ME_MAPPING(create_aggregate, sqlite_create_aggregate, NULL) + PHP_ME_MAPPING(create_function, sqlite_create_function, NULL) + PHP_ME_MAPPING(busy_timeout, sqlite_busy_timeout, NULL) + PHP_ME_MAPPING(last_error, sqlite_last_error, NULL) +/* PHP_ME_MAPPING(error_string, sqlite_error_string, NULL) static */ +/* PHP_ME_MAPPING(escape_string, sqlite_escape_string, NULL) static */ + {NULL, NULL, NULL} +}; + +function_entry sqlite_funcs_query[] = { + PHP_ME_MAPPING(fetch_array, sqlite_fetch_array, NULL) + PHP_ME_MAPPING(fetch_string, sqlite_fetch_string, NULL) + PHP_ME_MAPPING(fetch_all, sqlite_fetch_all, NULL) + PHP_ME_MAPPING(column, sqlite_column, NULL) + PHP_ME_MAPPING(changes, sqlite_changes, NULL) + PHP_ME_MAPPING(num_fields, sqlite_num_fields, NULL) + PHP_ME_MAPPING(field_name, sqlite_field_name, NULL) + /* spl_forward */ + PHP_ME_MAPPING(current, sqlite_current, NULL) + PHP_ME_MAPPING(next, sqlite_next, NULL) + PHP_ME_MAPPING(has_more, sqlite_has_more, NULL) + /* spl_sequence */ + PHP_ME_MAPPING(rewind, sqlite_rewind, NULL) + /* additional */ + PHP_ME_MAPPING(num_rows, sqlite_num_rows, NULL) + PHP_ME_MAPPING(seek, sqlite_seek, NULL) + {NULL, NULL, NULL} +}; + +function_entry sqlite_funcs_ub_query[] = { + PHP_ME_MAPPING(fetch_array, sqlite_fetch_array, NULL) + PHP_ME_MAPPING(fetch_string, sqlite_fetch_string, NULL) + PHP_ME_MAPPING(fetch_all, sqlite_fetch_all, NULL) + PHP_ME_MAPPING(column, sqlite_column, NULL) + PHP_ME_MAPPING(changes, sqlite_changes, NULL) + PHP_ME_MAPPING(num_fields, sqlite_num_fields, NULL) + PHP_ME_MAPPING(field_name, sqlite_field_name, NULL) + /* spl_forward */ + PHP_ME_MAPPING(current, sqlite_current, NULL) + PHP_ME_MAPPING(next, sqlite_next, NULL) + PHP_ME_MAPPING(has_more, sqlite_has_more, NULL) + {NULL, NULL, NULL} +}; + +function_entry sqlite_funcs_exception[] = { + {NULL, NULL, NULL} +}; zend_module_entry sqlite_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 @@ -156,7 +257,7 @@ zend_module_entry sqlite_module_entry = { sqlite_functions, PHP_MINIT(sqlite), NULL, - NULL, + PHP_RINIT(sqlite), PHP_RSHUTDOWN(sqlite), PHP_MINFO(sqlite), #if ZEND_MODULE_API_NO >= 20010901 @@ -609,6 +710,150 @@ static int php_sqlite_authorizer(void *autharg, int access_type, const char *arg } /* }}} */ +/* {{{ OO init/structure stuff */ +#define REGISTER_SQLITE_CLASS(name, parent) \ + { \ + zend_class_entry ce; \ + INIT_CLASS_ENTRY(ce, "sqlite_" # name, sqlite_funcs_ ## name); \ + ce.create_object = sqlite_object_new_ ## name; \ + sqlite_ce_ ## name = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \ + memcpy(&sqlite_object_handlers_ ## name, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \ + } + +zend_class_entry *sqlite_ce_db, *sqlite_ce_exception; +zend_class_entry *sqlite_ce_query, *sqlite_ce_ub_query; + +static zend_object_handlers sqlite_object_handlers_db; +static zend_object_handlers sqlite_object_handlers_query; +static zend_object_handlers sqlite_object_handlers_ub_query; +static zend_object_handlers sqlite_object_handlers_exception; + +typedef enum { + is_db, + is_result +} sqlite_obj_type; + +typedef struct _sqlite_object { + zend_object std; + sqlite_obj_type type; + union { + struct php_sqlite_db *db; + struct php_sqlite_result *res; + void *ptr; + } u; +} sqlite_object; + +static void sqlite_object_clone(void *object, void **object_clone TSRMLS_DC) +{ + /* TODO */ +} + +static int sqlite_free_persistent(list_entry *le, void *ptr TSRMLS_DC) +{ + return le->ptr == ptr; +} + +static void sqlite_object_dtor(void *object, zend_object_handle handle TSRMLS_DC) +{ + sqlite_object *intern = (sqlite_object *)object; + + zend_hash_destroy(intern->std.properties); + FREE_HASHTABLE(intern->std.properties); + + if (intern->u.ptr) { + if (intern->type == is_db) { + if (intern->u.db->rsrc_id) { + zend_list_delete(intern->u.db->rsrc_id); + zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) sqlite_free_persistent, &intern->u.ptr TSRMLS_CC); + } + } else { + real_result_dtor(intern->u.res TSRMLS_CC); + } + } + + efree(object); +} + +static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC) +{ + sqlite_object *intern; + zval *tmp; + + intern = emalloc(sizeof(sqlite_object)); + memset(intern, 0, sizeof(sqlite_object)); + intern->std.ce = class_type; + + ALLOC_HASHTABLE(intern->std.properties); + zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + + retval->handle = zend_objects_store_put(intern, sqlite_object_dtor, sqlite_object_clone TSRMLS_CC); + retval->handlers = handlers; +} + +static zend_object_value sqlite_object_new_db(zend_class_entry *class_type TSRMLS_DC) +{ + zend_object_value retval; + + sqlite_object_new(class_type, &sqlite_object_handlers_db, &retval TSRMLS_CC); + return retval; +} + +static zend_object_value sqlite_object_new_query(zend_class_entry *class_type TSRMLS_DC) +{ + zend_object_value retval; + + sqlite_object_new(class_type, &sqlite_object_handlers_query, &retval TSRMLS_CC); + return retval; +} + +static zend_object_value sqlite_object_new_ub_query(zend_class_entry *class_type TSRMLS_DC) +{ + zend_object_value retval; + + sqlite_object_new(class_type, &sqlite_object_handlers_ub_query, &retval TSRMLS_CC); + return retval; +} + +static zend_object_value sqlite_object_new_exception(zend_class_entry *class_type TSRMLS_DC) +{ + zend_object_value retval; + + sqlite_object_new(class_type, &sqlite_object_handlers_exception, &retval TSRMLS_CC); + return retval; +} + +#define SQLITE_REGISTER_OBJECT(_type, _object, _ptr) \ + { \ + sqlite_object *obj; \ + obj = (sqlite_object*)zend_object_store_get_object(_object TSRMLS_CC); \ + obj->type = is_ ## _type; \ + obj->u._type = _ptr; \ + } + +static zend_class_entry *sqlite_get_ce_query(zval *object TSRMLS_DC) +{ + return sqlite_ce_query; +} + +static zend_class_entry *sqlite_get_ce_ub_query(zval *object TSRMLS_DC) +{ + return sqlite_ce_ub_query; +} + +static zval * sqlite_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC) +{ + if (!object) { + ALLOC_ZVAL(object); + } + Z_TYPE_P(object) = IS_OBJECT; + object_init_ex(object, pce); + object->refcount = 1; + object->is_ref = 1; + return object; +} +/* }}} */ + static int init_sqlite_globals(zend_sqlite_globals *g) { g->assoc_case = 0; @@ -617,8 +862,15 @@ static int init_sqlite_globals(zend_sqlite_globals *g) PHP_MINIT_FUNCTION(sqlite) { + REGISTER_SQLITE_CLASS(db, NULL); + REGISTER_SQLITE_CLASS(query, NULL); + REGISTER_SQLITE_CLASS(ub_query, NULL); + REGISTER_SQLITE_CLASS(exception, zend_exception_get_default()); + sqlite_object_handlers_query.get_class_entry = sqlite_get_ce_query; + sqlite_object_handlers_ub_query.get_class_entry = sqlite_get_ce_ub_query; + ZEND_INIT_MODULE_GLOBALS(sqlite, init_sqlite_globals, NULL); - + REGISTER_INI_ENTRIES(); le_sqlite_db = zend_register_list_destructors_ex(php_sqlite_db_dtor, NULL, "sqlite database", module_number); @@ -662,6 +914,21 @@ PHP_MINIT_FUNCTION(sqlite) return SUCCESS; } +PHP_RINIT_FUNCTION(sqlite) +{ +#ifdef HAVE_SPL + if (!sqlite_ce_query->num_interfaces) { + spl_register_implement(sqlite_ce_query, spl_ce_forward TSRMLS_CC); + spl_register_implement(sqlite_ce_query, spl_ce_sequence TSRMLS_CC); + } + if (!sqlite_ce_ub_query->num_interfaces) { + spl_register_implement(sqlite_ce_ub_query, spl_ce_forward TSRMLS_CC); + } +#endif + + return SUCCESS; +} + PHP_MINFO_FUNCTION(sqlite) { php_info_print_table_start(); @@ -674,7 +941,7 @@ PHP_MINFO_FUNCTION(sqlite) DISPLAY_INI_ENTRIES(); } -static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *persistent_id, zval *return_value, zval *errmsg TSRMLS_DC) +static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *persistent_id, zval *return_value, zval *errmsg, zval *object TSRMLS_DC) { char *errtext = NULL; sqlite *sdb = NULL; @@ -692,7 +959,12 @@ static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *per sqlite_freemem(errtext); - RETVAL_FALSE; + /* if object is not an object then we're called from the factory() function */ + if (object && Z_TYPE_P(object) != IS_OBJECT) { + RETVAL_NULL(); + } else { + RETVAL_FALSE; + } return NULL; } @@ -715,7 +987,15 @@ static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *per * and IS backwards binary compatible with earlier versions */ sqlite_set_authorizer(sdb, php_sqlite_authorizer, NULL); - db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, persistent_id ? le_sqlite_pdb : le_sqlite_db); + db->rsrc_id = ZEND_REGISTER_RESOURCE(object ? NULL : return_value, db, persistent_id ? le_sqlite_pdb : le_sqlite_db); + if (object) { + /* if object is not an object then we're called from the factory() function */ + if (Z_TYPE_P(object) != IS_OBJECT) { + sqlite_instanciate(sqlite_ce_db, object TSRMLS_CC); + } + /* and now register the object */ + SQLITE_REGISTER_OBJECT(db, object, db) + } if (persistent_id) { list_entry le; @@ -790,7 +1070,7 @@ PHP_FUNCTION(sqlite_popen) } /* now we need to open the database */ - php_sqlite_open(fullpath, mode, hashkey, return_value, errmsg TSRMLS_CC); + php_sqlite_open(fullpath, mode, hashkey, return_value, errmsg, NULL TSRMLS_CC); efree(fullpath); efree(hashkey); @@ -805,23 +1085,70 @@ PHP_FUNCTION(sqlite_open) char *filename; long filename_len; zval *errmsg = NULL; + zval *object = getThis(); + php_set_error_handling(object ? EH_THROW : EH_NORMAL, zend_exception_get_default() TSRMLS_CC); if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &filename, &filename_len, &mode, &errmsg)) { + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); return; } if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) { if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - RETURN_FALSE; + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); + if (object) { + RETURN_NULL(); + } else { + RETURN_FALSE; + } } - + if (php_check_open_basedir(filename TSRMLS_CC)) { - RETURN_FALSE; + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); + if (object) { + RETURN_NULL(); + } else { + RETURN_FALSE; + } } } - - php_sqlite_open(filename, mode, NULL, return_value, errmsg TSRMLS_CC); + + php_sqlite_open(filename, mode, NULL, return_value, errmsg, object TSRMLS_CC); + + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto object factory(string filename [, int mode, string &errmessage]) + Opens a SQLite database and create an object for it. Will create the database if it does not exist */ +PHP_FUNCTION(sqlite_factory) +{ + int mode = 0666; + char *filename; + long filename_len; + zval *errmsg = NULL; + + php_set_error_handling(EH_THROW, sqlite_ce_exception TSRMLS_CC); + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", + &filename, &filename_len, &mode, &errmsg)) { + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); + RETURN_NULL(); + } + + if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); + RETURN_NULL(); + } + + if (php_check_open_basedir(filename TSRMLS_CC)) { + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); + RETURN_NULL(); + } + + php_sqlite_open(filename, mode, NULL, return_value, errmsg, return_value TSRMLS_CC); + + php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC); } /* }}} */ @@ -832,13 +1159,20 @@ PHP_FUNCTION(sqlite_busy_timeout) zval *zdb; struct php_sqlite_db *db; long ms; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zdb, &ms)) { - return; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ms)) { + return; + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zdb, &ms)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); - sqlite_busy_timeout(db->db, ms); } /* }}} */ @@ -849,18 +1183,17 @@ PHP_FUNCTION(sqlite_close) { zval *zdb; struct php_sqlite_db *db; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { - return; - } - DB_FROM_ZVAL(db, &zdb); - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { - return; + if (object) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Ignored, you must destruct the object instead"); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); - zend_list_delete(Z_RESVAL_P(zdb)); } /* }}} */ @@ -955,7 +1288,7 @@ next_row: /* }}} */ /* {{{ sqlite_query */ -void sqlite_query(struct php_sqlite_db *db, char *sql, long sql_len, int mode, int buffered, zval *return_value, struct php_sqlite_result *rres TSRMLS_DC) +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 *rres TSRMLS_DC) { struct php_sqlite_result res; int ret; @@ -992,8 +1325,18 @@ void sqlite_query(struct php_sqlite_db *db, char *sql, long sql_len, int mode, i rres->curr_row = 0; - if (return_value) { - ZEND_REGISTER_RESOURCE(return_value, rres, le_sqlite_result); + if (object) { + sqlite_object *obj; + if (buffered) { + sqlite_instanciate(sqlite_ce_query, return_value TSRMLS_CC); + } else { + sqlite_instanciate(sqlite_ce_ub_query, return_value TSRMLS_CC); + } + obj = (sqlite_object *) zend_object_store_get_object(return_value TSRMLS_CC); + obj->type = is_result; + obj->u.res = rres; + } else if (return_value) { + ZEND_REGISTER_RESOURCE(object ? NULL : return_value, rres, le_sqlite_result); } } /* }}} */ @@ -1008,15 +1351,22 @@ PHP_FUNCTION(sqlite_unbuffered_query) long sql_len; int mode = PHPSQLITE_BOTH; char *errtext = NULL; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &sql, &sql_len, &mode)) { + return; + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &sql, &sql_len, &zdb, &mode) && FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &sql, &sql_len, &mode)) { - return; + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); - /* avoid doing work if we can */ if (!return_value_used) { db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext); @@ -1027,8 +1377,8 @@ PHP_FUNCTION(sqlite_unbuffered_query) } return; } - - sqlite_query(db, sql, sql_len, mode, 0, return_value, NULL TSRMLS_CC); + + sqlite_query(object, db, sql, sql_len, mode, 0, return_value, NULL TSRMLS_CC); } /* }}} */ @@ -1042,13 +1392,21 @@ PHP_FUNCTION(sqlite_query) long sql_len; int mode = PHPSQLITE_BOTH; char *errtext = NULL; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, - ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &sql, &sql_len, &zdb, &mode) && - FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &sql, &sql_len, &mode)) { - return; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &sql, &sql_len, &mode)) { + return; + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, + ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &sql, &sql_len, &zdb, &mode) && + FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &sql, &sql_len, &mode)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); /* avoid doing work if we can */ if (!return_value_used) { @@ -1060,17 +1418,17 @@ PHP_FUNCTION(sqlite_query) } return; } - - sqlite_query(db, sql, sql_len, mode, 1, return_value, NULL TSRMLS_CC); + + sqlite_query(object, db, sql, sql_len, mode, 1, return_value, NULL TSRMLS_CC); } /* }}} */ /* {{{ php_sqlite_fetch_array */ 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) { - int j, buffered = res->buffered; + int j, n = res->ncolumns, buffered = res->buffered; const char **rowdata, **colnames; - + /* check range of the row */ if (res->curr_row >= res->nrows) { /* no more */ @@ -1086,7 +1444,7 @@ static void php_sqlite_fetch_array(struct php_sqlite_result *res, int mode, zend /* now populate the result */ array_init(return_value); - for (j = 0; j < res->ncolumns; j++) { + for (j = 0; j < n; j++) { zval *decoded; MAKE_STD_ZVAL(decoded); @@ -1168,7 +1526,7 @@ static void php_sqlite_fetch_column(struct php_sqlite_result *res, zval *which, if (rowdata[j] == NULL) { RETURN_NULL(); - } else if (decode_binary && rowdata[j][0] == '\x01') { + } else if (decode_binary && rowdata[j] != NULL && rowdata[j][0] == '\x01') { int l = strlen(rowdata[j]); char *decoded = emalloc(l); l = sqlite_decode_binary(rowdata[j]+1, decoded); @@ -1177,12 +1535,12 @@ static void php_sqlite_fetch_column(struct php_sqlite_result *res, zval *which, if (!res->buffered) { efree((char*)rowdata[j]); rowdata[j] = NULL; - } + } } else { RETVAL_STRING((char*)rowdata[j], res->buffered); if (!res->buffered) { rowdata[j] = NULL; - } + } } } /* }}} */ @@ -1195,13 +1553,24 @@ PHP_FUNCTION(sqlite_fetch_all) int mode = PHPSQLITE_BOTH; zend_bool decode_binary = 1; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) { - return; - } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); - if (ZEND_NUM_ARGS() < 2) { - mode = res->mode; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) { + return; + } + RES_FROM_OBJECT(res, object); + if (!ZEND_NUM_ARGS()) { + mode = res->mode; + } + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); + if (ZEND_NUM_ARGS() < 2) { + mode = res->mode; + } } if (res->curr_row >= res->nrows && res->nrows) { @@ -1230,13 +1599,24 @@ PHP_FUNCTION(sqlite_fetch_array) int mode = PHPSQLITE_BOTH; zend_bool decode_binary = 1; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) { - return; - } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); - if (ZEND_NUM_ARGS() < 2) { - mode = res->mode; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) { + return; + } + RES_FROM_OBJECT(res, object); + if (!ZEND_NUM_ARGS()) { + mode = res->mode; + } + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); + if (ZEND_NUM_ARGS() < 2) { + mode = res->mode; + } } php_sqlite_fetch_array(res, mode, decode_binary, 1, return_value TSRMLS_CC); @@ -1255,13 +1635,21 @@ PHP_FUNCTION(sqlite_array_query) int mode = PHPSQLITE_BOTH; char *errtext = NULL; zend_bool decode_binary = 1; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, - ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &sql, &sql_len, &zdb, &mode, &decode_binary) && - FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &sql, &sql_len, &mode, &decode_binary)) { - return; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &sql, &sql_len, &mode, &decode_binary)) { + return; + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, + ZEND_NUM_ARGS() TSRMLS_CC, "sr|lb", &sql, &sql_len, &zdb, &mode, &decode_binary) && + FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zdb, &sql, &sql_len, &mode, &decode_binary)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); /* avoid doing work if we can */ if (!return_value_used) { @@ -1273,9 +1661,9 @@ PHP_FUNCTION(sqlite_array_query) } return; } - + rres = (struct php_sqlite_result *)emalloc(sizeof(*rres)); - sqlite_query(db, sql, sql_len, mode, 0, NULL, rres TSRMLS_CC); + sqlite_query(NULL, db, sql, sql_len, mode, 0, NULL, rres TSRMLS_CC); array_init(return_value); @@ -1298,11 +1686,19 @@ PHP_FUNCTION(sqlite_fetch_string) char *decoded = NULL; int decoded_len; const char **rowdata; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zres, &decode_binary)) { - return; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &decode_binary)) { + return; + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zres, &decode_binary)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); /* check if there are any more rows on the cursor */ if (res->curr_row >= res->nrows) { @@ -1360,13 +1756,24 @@ PHP_FUNCTION(sqlite_current) int mode = PHPSQLITE_BOTH; zend_bool decode_binary = 1; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) { - return; - } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); - if (ZEND_NUM_ARGS() < 2) { - mode = res->mode; + if (object) { + if (ZEND_NUM_ARGS() && FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) { + return; + } + RES_FROM_OBJECT(res, object); + if (!ZEND_NUM_ARGS()) { + mode = res->mode; + } + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); + if (ZEND_NUM_ARGS() < 2) { + mode = res->mode; + } } php_sqlite_fetch_array(res, mode, decode_binary, 0, return_value TSRMLS_CC); @@ -1381,11 +1788,19 @@ PHP_FUNCTION(sqlite_column) zval *which; zend_bool decode_binary = 1; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zres, &which, &decode_binary)) { - return; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &which, &decode_binary)) { + return; + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zres, &which, &decode_binary)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); php_sqlite_fetch_column(res, which, decode_binary, return_value TSRMLS_CC); } @@ -1419,13 +1834,20 @@ PHP_FUNCTION(sqlite_changes) { zval *zdb; struct php_sqlite_db *db; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { - return; + if (object) { + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); - RETURN_LONG(sqlite_changes(db->db)); } /* }}} */ @@ -1436,13 +1858,20 @@ PHP_FUNCTION(sqlite_last_insert_rowid) { zval *zdb; struct php_sqlite_db *db; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { - return; + if (object) { + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); - RETURN_LONG(sqlite_last_insert_rowid(db->db)); } /* }}} */ @@ -1453,13 +1882,20 @@ PHP_FUNCTION(sqlite_num_rows) { zval *zres; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { - return; + if (object) { + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); - if (res->buffered) { RETURN_LONG(res->nrows); } else { @@ -1475,13 +1911,21 @@ PHP_FUNCTION(sqlite_has_more) { zval *zres; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { - return; + if (object) { + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); - RETURN_BOOL(res->nrows && res->curr_row < res->nrows); /* curr_row may be -1 */ + RETURN_BOOL(res->curr_row < res->nrows && res->nrows); /* curr_row may be -1 */ } /* }}} */ @@ -1491,13 +1935,20 @@ PHP_FUNCTION(sqlite_num_fields) { zval *zres; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { - return; + if (object) { + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); - RETURN_LONG(res->ncolumns); } /* }}} */ @@ -1509,13 +1960,20 @@ PHP_FUNCTION(sqlite_field_name) zval *zres; struct php_sqlite_result *res; int field; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &field)) { - return; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &field)) { + return; + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zres, &field)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); - if (field < 0 || field >= res->ncolumns) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %d out of range", field); RETURN_FALSE; @@ -1532,13 +1990,20 @@ PHP_FUNCTION(sqlite_seek) zval *zres; struct php_sqlite_result *res; int row; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &row)) { - return; + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &row)) { + return; + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &row)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); - if (!res->buffered) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set"); RETURN_FALSE; @@ -1560,11 +2025,19 @@ PHP_FUNCTION(sqlite_rewind) { zval *zres; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { - return; + if (object) { + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); if (!res->buffered) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set"); @@ -1587,11 +2060,19 @@ PHP_FUNCTION(sqlite_next) { zval *zres; struct php_sqlite_result *res; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { - return; + if (object) { + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT + } + RES_FROM_OBJECT(res, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) { + return; + } + ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); } - ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result); if (!res->buffered && res->vm) { php_sqlite_fetch(res TSRMLS_CC); @@ -1645,13 +2126,20 @@ PHP_FUNCTION(sqlite_last_error) { zval *zdb; struct php_sqlite_db *db; + zval *object = getThis(); - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { - return; + if (object) { + if (ZEND_NUM_ARGS() != 0) { + WRONG_PARAM_COUNT + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); - RETURN_LONG(db->last_err_code); } /* }}} */ @@ -1750,11 +2238,19 @@ PHP_FUNCTION(sqlite_create_aggregate) struct php_sqlite_agg_functions *funcs; char *callable = NULL; long num_args = -1; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rszz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) { - return; + zval *object = getThis(); + + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) { + return; + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rszz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); if (!zend_is_callable(zstep, 0, &callable)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "step function `%s' is not callable", callable); @@ -1770,6 +2266,7 @@ PHP_FUNCTION(sqlite_create_aggregate) } efree(callable); + if (prep_callback_struct(db, 1, funcname, zstep, zfinal, &funcs) == DO_REG) { sqlite_create_aggregate(db->db, funcname, num_args, php_sqlite_agg_step_function_callback, @@ -1792,10 +2289,19 @@ PHP_FUNCTION(sqlite_create_function) char *callable = NULL; long num_args = -1; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) { - return; + zval *object = getThis(); + + if (object) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) { + return; + } + DB_FROM_OBJECT(db, object); + } else { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) { + return; + } + DB_FROM_ZVAL(db, &zdb); } - DB_FROM_ZVAL(db, &zdb); if (!zend_is_callable(zcall, 0, &callable)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "function `%s' is not callable", callable); diff --git a/ext/sqlite/tests/blankdb_oo.inc b/ext/sqlite/tests/blankdb_oo.inc new file mode 100755 index 0000000000..05609bddb7 --- /dev/null +++ b/ext/sqlite/tests/blankdb_oo.inc @@ -0,0 +1,13 @@ +close(); + } + unlink($dbname); +} +register_shutdown_function("cleanup"); +$db = new sqlite_db($dbname); +?> diff --git a/ext/sqlite/tests/sqlite_oo_001.phpt b/ext/sqlite/tests/sqlite_oo_001.phpt new file mode 100755 index 0000000000..38865160f7 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_001.phpt @@ -0,0 +1,17 @@ +--TEST-- +sqlite-oo: sqlite_open/close +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +object(sqlite_db)#%d (0) { +} +Done diff --git a/ext/sqlite/tests/sqlite_oo_002.phpt b/ext/sqlite/tests/sqlite_oo_002.phpt new file mode 100755 index 0000000000..d3289b4d87 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_002.phpt @@ -0,0 +1,41 @@ +--TEST-- +sqlite-oo: Simple insert/select +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))")); +var_dump($db->query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)")); +$r = $db->query("SELECT * from foo"); +var_dump($r); +var_dump($r->fetch_array()); +?> +--EXPECTF-- +object(sqlite_db)#%d (0) { +} +object(sqlite_query)#%d (0) { +} +object(sqlite_query)#%d (0) { +} +object(sqlite_query)#%d (0) { +} +array(6) { + [0]=> + string(10) "2002-01-02" + ["c1"]=> + string(10) "2002-01-02" + [1]=> + string(8) "12:49:00" + ["c2"]=> + string(8) "12:49:00" + [2]=> + NULL + ["c3"]=> + NULL +} diff --git a/ext/sqlite/tests/sqlite_oo_003.phpt b/ext/sqlite/tests/sqlite_oo_003.phpt new file mode 100755 index 0000000000..f498038936 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_003.phpt @@ -0,0 +1,51 @@ +--TEST-- +sqlite-oo: Simple insert/select, different result represenatation +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))"); +$db->query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)"); +$r = $db->query("SELECT * from foo"); +var_dump($r->fetch_array(SQLITE_BOTH)); +$r = $db->query("SELECT * from foo"); +var_dump($r->fetch_array(SQLITE_NUM)); +$r = $db->query("SELECT * from foo"); +var_dump($r->fetch_array(SQLITE_ASSOC)); +?> +--EXPECT-- +array(6) { + [0]=> + string(10) "2002-01-02" + ["c1"]=> + string(10) "2002-01-02" + [1]=> + string(8) "12:49:00" + ["c2"]=> + string(8) "12:49:00" + [2]=> + NULL + ["c3"]=> + NULL +} +array(3) { + [0]=> + string(10) "2002-01-02" + [1]=> + string(8) "12:49:00" + [2]=> + NULL +} +array(3) { + ["c1"]=> + string(10) "2002-01-02" + ["c2"]=> + string(8) "12:49:00" + ["c3"]=> + NULL +} diff --git a/ext/sqlite/tests/sqlite_oo_008.phpt b/ext/sqlite/tests/sqlite_oo_008.phpt new file mode 100755 index 0000000000..4340fb6e3a --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_008.phpt @@ -0,0 +1,43 @@ +--TEST-- +sqlite-oo: fetch all (buffered) +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE strings(a VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('$str')"); +} + +$r = $db->query("SELECT a from strings"); +while ($row = $r->fetch_array(SQLITE_NUM)) { + var_dump($row); +} +echo "DONE!\n"; +?> +--EXPECT-- +array(1) { + [0]=> + string(3) "one" +} +array(1) { + [0]=> + string(3) "two" +} +array(1) { + [0]=> + string(5) "three" +} +DONE! diff --git a/ext/sqlite/tests/sqlite_oo_009.phpt b/ext/sqlite/tests/sqlite_oo_009.phpt new file mode 100755 index 0000000000..184804cfc9 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_009.phpt @@ -0,0 +1,43 @@ +--TEST-- +sqlite-oo: fetch all (unbuffered) +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE strings(a VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('$str')"); +} + +$r = $db->unbuffered_query("SELECT a from strings"); +while ($row = $r->fetch_array(SQLITE_NUM)) { + var_dump($row); +} +echo "DONE!\n"; +?> +--EXPECT-- +array(1) { + [0]=> + string(3) "one" +} +array(1) { + [0]=> + string(3) "two" +} +array(1) { + [0]=> + string(5) "three" +} +DONE! diff --git a/ext/sqlite/tests/sqlite_oo_010.phpt b/ext/sqlite/tests/sqlite_oo_010.phpt new file mode 100755 index 0000000000..dd386adf36 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_010.phpt @@ -0,0 +1,44 @@ +--TEST-- +sqlite-oo: fetch all (iterator) +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE strings(a VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('$str')"); +} + +$r = $db->unbuffered_query("SELECT a from strings", SQLITE_NUM); +while ($row = $r->has_more()) { + var_dump($r->current()); + $r->next(); +} +echo "DONE!\n"; +?> +--EXPECT-- +array(1) { + [0]=> + string(3) "one" +} +array(1) { + [0]=> + string(3) "two" +} +array(1) { + [0]=> + string(5) "three" +} +DONE! diff --git a/ext/sqlite/tests/sqlite_oo_011.phpt b/ext/sqlite/tests/sqlite_oo_011.phpt new file mode 100755 index 0000000000..c8fdfd1200 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_011.phpt @@ -0,0 +1,27 @@ +--TEST-- +sqlite-oo: returned associative column names +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE foo (c1 char, c2 char, c3 char)"); +$db->query("CREATE TABLE bar (c1 char, c2 char, c3 char)"); +$db->query("INSERT INTO foo VALUES ('1', '2', '3')"); +$db->query("INSERT INTO bar VALUES ('4', '5', '6')"); +$r = $db->query("SELECT * from foo, bar", SQLITE_ASSOC); +var_dump($r->fetch_array()); +?> +--EXPECT-- +array(3) { + ["c1"]=> + string(1) "4" + ["c2"]=> + string(1) "5" + ["c3"]=> + string(1) "6" +} diff --git a/ext/sqlite/tests/sqlite_oo_012.phpt b/ext/sqlite/tests/sqlite_oo_012.phpt new file mode 100755 index 0000000000..b1a26440c8 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_012.phpt @@ -0,0 +1,35 @@ +--TEST-- +sqlite-oo: read field names +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE strings(foo VARCHAR, bar VARCHAR, baz VARCHAR)"); + +echo "Buffered\n"; +$r = $db->query("SELECT * from strings"); +for($i=0; $i<$r->num_fields(); $i++) { + var_dump($r->field_name($i)); +} +echo "Unbuffered\n"; +$r = $db->unbuffered_query("SELECT * from strings"); +for($i=0; $i<$r->num_fields(); $i++) { + var_dump($r->field_name($i)); +} +echo "DONE!\n"; +?> +--EXPECT-- +Buffered +string(3) "foo" +string(3) "bar" +string(3) "baz" +Unbuffered +string(3) "foo" +string(3) "bar" +string(3) "baz" +DONE! diff --git a/ext/sqlite/tests/sqlite_oo_013.phpt b/ext/sqlite/tests/sqlite_oo_013.phpt new file mode 100755 index 0000000000..e1bb392819 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_013.phpt @@ -0,0 +1,75 @@ +--TEST-- +sqlite-oo: fetch column +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- + 'one', 1 => 'two'), + array (0 => 'three', 1 => 'four') + ); + +$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')"); +} + +echo "====BUFFERED====\n"; +$r = $db->query("SELECT a, b from strings"); +while ($r->has_more()) { + var_dump($r->current(SQLITE_NUM)); + var_dump($r->column(0)); + var_dump($r->column(1)); + var_dump($r->column('a')); + var_dump($r->column('b')); + $r->next(); +} +echo "====UNBUFFERED====\n"; +$r = $db->unbuffered_query("SELECT a, b from strings"); +while ($r->has_more()) { + var_dump($r->column(0)); + var_dump($r->column('b')); + var_dump($r->column(1)); + var_dump($r->column('a')); + $r->next(); +} +echo "DONE!\n"; +?> +--EXPECT-- +====BUFFERED==== +array(2) { + [0]=> + string(3) "one" + [1]=> + string(3) "two" +} +string(3) "one" +string(3) "two" +string(3) "one" +string(3) "two" +array(2) { + [0]=> + string(5) "three" + [1]=> + string(4) "four" +} +string(5) "three" +string(4) "four" +string(5) "three" +string(4) "four" +====UNBUFFERED==== +string(3) "one" +string(3) "two" +NULL +NULL +string(5) "three" +string(4) "four" +NULL +NULL +DONE! diff --git a/ext/sqlite/tests/sqlite_oo_014.phpt b/ext/sqlite/tests/sqlite_oo_014.phpt new file mode 100755 index 0000000000..041b18d250 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_014.phpt @@ -0,0 +1,118 @@ +--TEST-- +sqlite-oo: fetch all +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE strings(a VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('$str')"); +} + +echo "unbuffered twice\n"; +$r = $db->unbuffered_query("SELECT a from strings", SQLITE_NUM); +var_dump($r->fetch_all()); +var_dump($r->fetch_all()); + +echo "unbuffered with fetch_array\n"; +$r = $db->unbuffered_query("SELECT a from strings", SQLITE_NUM); +var_dump($r->fetch_array()); +var_dump($r->fetch_all()); + +echo "buffered\n"; +$r = $db->query("SELECT a from strings", SQLITE_NUM); +var_dump($r->fetch_all()); +var_dump($r->fetch_array()); +var_dump($r->fetch_all()); + +echo "DONE!\n"; +?> +--EXPECTF-- +unbuffered twice +array(3) { + [0]=> + array(1) { + [0]=> + string(3) "one" + } + [1]=> + array(1) { + [0]=> + string(3) "two" + } + [2]=> + array(1) { + [0]=> + string(5) "three" + } +} + +Notice: fetch_all(): One or more rowsets were already returned in %ssqlite_oo_014.php on line %d +array(0) { +} +unbuffered with fetch_array +array(1) { + [0]=> + string(3) "one" +} +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "two" + } + [1]=> + array(1) { + [0]=> + string(5) "three" + } +} +buffered +array(3) { + [0]=> + array(1) { + [0]=> + string(3) "one" + } + [1]=> + array(1) { + [0]=> + string(3) "two" + } + [2]=> + array(1) { + [0]=> + string(5) "three" + } +} +bool(false) +array(3) { + [0]=> + array(1) { + [0]=> + string(3) "one" + } + [1]=> + array(1) { + [0]=> + string(3) "two" + } + [2]=> + array(1) { + [0]=> + string(5) "three" + } +} +DONE! diff --git a/ext/sqlite/tests/sqlite_oo_015.phpt b/ext/sqlite/tests/sqlite_oo_015.phpt new file mode 100755 index 0000000000..5fc90e2c8c --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_015.phpt @@ -0,0 +1,47 @@ +--TEST-- +sqlite-oo: array_query +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE strings(a VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('$str')"); +} + +$res = $db->array_query("SELECT a from strings", SQLITE_NUM); +var_dump($res); + +echo "DONE!\n"; +?> +--EXPECTF-- +array(3) { + [0]=> + array(1) { + [0]=> + string(3) "one" + } + [1]=> + array(1) { + [0]=> + string(3) "two" + } + [2]=> + array(1) { + [0]=> + string(5) "three" + } +} +DONE! diff --git a/ext/sqlite/tests/sqlite_oo_016.phpt b/ext/sqlite/tests/sqlite_oo_016.phpt new file mode 100755 index 0000000000..c346bf2434 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_016.phpt @@ -0,0 +1,42 @@ +--TEST-- +sqlite-oo: fetch string +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- + 'one', 1 => 'two'), + array (0 => 'three', 1 => 'four') + ); + +$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')"); +} + +echo "====BUFFERED====\n"; +$r = $db->query("SELECT a, b from strings"); +while ($r->has_more()) { + var_dump($r->fetch_string()); +} +echo "====UNBUFFERED====\n"; +$r = $db->unbuffered_query("SELECT a, b from strings"); +while ($r->has_more()) { + var_dump($r->fetch_string()); +} +echo "DONE!\n"; +?> +--EXPECT-- +====BUFFERED==== +string(3) "one" +string(5) "three" +====UNBUFFERED==== +string(3) "one" +string(5) "three" +DONE! diff --git a/ext/sqlite/tests/sqlite_oo_020.phpt b/ext/sqlite/tests/sqlite_oo_020.phpt new file mode 100755 index 0000000000..e8e2d631f6 --- /dev/null +++ b/ext/sqlite/tests/sqlite_oo_020.phpt @@ -0,0 +1,63 @@ +--TEST-- +sqlite-oo: factory and exception +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +close(); + } + unlink($dbname); +} +register_shutdown_function("cleanup"); + +try { + $db = sqlite_factory(); +} catch(sqlite_exception $err) { + echo "Message: ".$err->getmessage()."\n"; + echo "File: ".$err->getfile()."\n"; +} + +$db = sqlite_factory($dbname); + +$data = array( + array (0 => 'one', 1 => 'two'), + array (0 => 'three', 1 => 'four') + ); + +$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')"); +} + +$r = $db->unbuffered_query("SELECT a, b from strings"); +while ($r->has_more()) { + var_dump($r->current(SQLITE_NUM)); + $r->next(); +} +echo "DONE!\n"; +?> +--EXPECTF-- +Message: sqlite_factory() expects at least 1 parameter, 0 given +File: %s/sqlite_oo_020.php +array(2) { + [0]=> + string(3) "one" + [1]=> + string(3) "two" +} +array(2) { + [0]=> + string(5) "three" + [1]=> + string(4) "four" +} +DONE! diff --git a/ext/sqlite/tests/sqlite_spl_001.phpt b/ext/sqlite/tests/sqlite_spl_001.phpt new file mode 100755 index 0000000000..3220c5af19 --- /dev/null +++ b/ext/sqlite/tests/sqlite_spl_001.phpt @@ -0,0 +1,114 @@ +--TEST-- +sqlite-spl: sqlite / spl integration +--INI-- +sqlite.assoc_case=0 +--SKIPIF-- + +--FILE-- +query("CREATE TABLE strings(a VARCHAR)"); + +foreach ($data as $str) { + $db->query("INSERT INTO strings VALUES('$str')"); +} + +echo "====UNBUFFERED====\n"; +$r = $db->unbuffered_query("SELECT a from strings", SQLITE_NUM); +var_dump(class_implements($r)); +foreach($r as $row) { + var_dump($row); +} +echo "====NO-MORE====\n"; +foreach($r as $row) { + var_dump($row); +} +echo "====DIRECT====\n"; +foreach($db->unbuffered_query("SELECT a from strings", SQLITE_NUM) as $row) { + var_dump($row); +} +echo "====BUFFERED====\n"; +$r = $db->query("SELECT a from strings", SQLITE_NUM); +var_dump(class_implements($r)); +foreach($r as $row) { + var_dump($row); +} +foreach($r as $row) { + var_dump($row); +} +echo "DONE!\n"; +?> +--EXPECT-- +====UNBUFFERED==== +array(1) { + ["spl_forward"]=> + string(11) "spl_forward" +} +array(1) { + [0]=> + string(3) "one" +} +array(1) { + [0]=> + string(3) "two" +} +array(1) { + [0]=> + string(5) "three" +} +====NO-MORE==== +====DIRECT==== +array(1) { + [0]=> + string(3) "one" +} +array(1) { + [0]=> + string(3) "two" +} +array(1) { + [0]=> + string(5) "three" +} +====BUFFERED==== +array(2) { + ["spl_forward"]=> + string(11) "spl_forward" + ["spl_sequence"]=> + string(12) "spl_sequence" +} +array(1) { + [0]=> + string(3) "one" +} +array(1) { + [0]=> + string(3) "two" +} +array(1) { + [0]=> + string(5) "three" +} +array(1) { + [0]=> + string(3) "one" +} +array(1) { + [0]=> + string(3) "two" +} +array(1) { + [0]=> + string(5) "three" +} +DONE! -- 2.40.0