wez Thu Jun 9 22:50:38 2005 EDT Modified files: /php-src/ext/pdo_sqlite php_pdo_sqlite_int.h sqlite_driver.c Log: work in progress on UDF. Something is hokey in HEAD, checking it in to try it on another box. http://cvs.php.net/diff.php/php-src/ext/pdo_sqlite/php_pdo_sqlite_int.h?r1=1.2&r2=1.3&ty=u Index: php-src/ext/pdo_sqlite/php_pdo_sqlite_int.h diff -u php-src/ext/pdo_sqlite/php_pdo_sqlite_int.h:1.2 php-src/ext/pdo_sqlite/php_pdo_sqlite_int.h:1.3 --- php-src/ext/pdo_sqlite/php_pdo_sqlite_int.h:1.2 Sun Sep 26 16:46:35 2004 +++ php-src/ext/pdo_sqlite/php_pdo_sqlite_int.h Thu Jun 9 22:50:37 2005 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | + | Copyright (c) 1997-2005 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_pdo_sqlite_int.h,v 1.2 2004/09/26 20:46:35 wez Exp $ */ +/* $Id: php_pdo_sqlite_int.h,v 1.3 2005/06/10 02:50:37 wez Exp $ */ #ifndef PHP_PDO_SQLITE_INT_H #define PHP_PDO_SQLITE_INT_H @@ -30,9 +30,26 @@ char *errmsg; } pdo_sqlite_error_info; +struct pdo_sqlite_fci { + zend_fcall_info fci; + zend_fcall_info_cache fcc; +}; + +struct pdo_sqlite_func { + struct pdo_sqlite_func *next; + + zval *func, *step, *fini; + int argc; + const char *funcname; + + /* accelerated callback references */ + struct pdo_sqlite_fci afunc, astep, afini; +}; + typedef struct { sqlite3 *db; pdo_sqlite_error_info einfo; + struct pdo_sqlite_func *funcs; } pdo_sqlite_db_handle; typedef struct { http://cvs.php.net/diff.php/php-src/ext/pdo_sqlite/sqlite_driver.c?r1=1.15&r2=1.16&ty=u Index: php-src/ext/pdo_sqlite/sqlite_driver.c diff -u php-src/ext/pdo_sqlite/sqlite_driver.c:1.15 php-src/ext/pdo_sqlite/sqlite_driver.c:1.16 --- php-src/ext/pdo_sqlite/sqlite_driver.c:1.15 Sat Feb 26 12:27:51 2005 +++ php-src/ext/pdo_sqlite/sqlite_driver.c Thu Jun 9 22:50:37 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: sqlite_driver.c,v 1.15 2005/02/26 17:27:51 wez Exp $ */ +/* $Id: sqlite_driver.c,v 1.16 2005/06/10 02:50:37 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -96,11 +96,44 @@ return 1; } +static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC) +{ + struct pdo_sqlite_func *func; + + while (H->funcs) { + func = H->funcs; + H->funcs = func->next; + + if (H->db) { + /* delete the function from the handle */ + sqlite3_create_function(H->db, + func->funcname, + func->argc, + SQLITE_UTF8, + func, + NULL, NULL, NULL); + } + + efree((char*)func->funcname); + if (func->func) { + zval_ptr_dtor(&func->func); + } + if (func->step) { + zval_ptr_dtor(&func->step); + } + if (func->fini) { + zval_ptr_dtor(&func->fini); + } + efree(func); + } +} + static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ { pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data; if (H) { + pdo_sqlite_cleanup_callbacks(H TSRMLS_CC); if (H->db) { sqlite3_close(H->db); H->db = NULL; @@ -245,18 +278,169 @@ return 0; } -static PHP_FUNCTION(sqlite_create_function) +static int do_callback(struct pdo_sqlite_fci *fc, zval *cb, + int argc, sqlite3_value **argv, zval **retval TSRMLS_DC) +{ + zval ***zargs = NULL; + int i; + int ret; + + fc->fci.size = sizeof(fc->fci); + fc->fci.function_table = EG(function_table); + fc->fci.function_name = cb; + fc->fci.symbol_table = NULL; + fc->fci.object_pp = NULL; + fc->fci.retval_ptr_ptr = retval; + fc->fci.param_count = argc; + + /* build up the params */ + if (argc) { + zargs = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); + + for (i = 0; i < argc; i++) { + zargs[i] = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*zargs[i]); + + /* get the value */ + switch (sqlite3_value_type(argv[i])) { + case SQLITE_INTEGER: + ZVAL_LONG(*zargs[i], sqlite3_value_int(argv[i])); + break; + + case SQLITE_FLOAT: + ZVAL_DOUBLE(*zargs[i], sqlite3_value_double(argv[i])); + break; + + case SQLITE_NULL: + ZVAL_NULL(*zargs[i]); + break; + + case SQLITE_BLOB: + case SQLITE3_TEXT: + default: + ZVAL_STRINGL(*zargs[i], (char*)sqlite3_value_text(argv[i]), + sqlite3_value_bytes(argv[i]), 1); + break; + } + } + } + + + fc->fci.params = zargs; + + if ((ret = zend_call_function(&fc->fci, &fc->fcc TSRMLS_CC)) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback"); + } + + /* clean up the params */ + if (argc) { + for (i = 0; i < argc; i++) { + zval_ptr_dtor(zargs[i]); + efree(zargs[i]); + } + efree(zargs); + } + + return ret; +} + +static void php_sqlite3_func_callback(sqlite3_context *context, int argc, + sqlite3_value **argv) { - /* TODO: implement this stuff */ + struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)context; + zval *retval = NULL; + TSRMLS_FETCH(); + + do_callback(&func->afunc, func->func, argc, argv, &retval TSRMLS_CC); +} + +static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc, + sqlite3_value **argv) +{ + struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)context; + zval *retval = NULL; + TSRMLS_FETCH(); + + do_callback(&func->astep, func->step, argc, argv, &retval TSRMLS_CC); +} + +static void php_sqlite3_func_final_callback(sqlite3_context *context) +{ + struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)context; + zval *retval = NULL; + TSRMLS_FETCH(); + + do_callback(&func->afini, func->fini, 0, NULL, &retval TSRMLS_CC); } +/* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount]) + Registers a UDF with the sqlite db handle */ +static PHP_METHOD(SQLite, sqliteCreateFunction) +{ + struct pdo_sqlite_func *func; + zval *callback; + char *func_name; + int func_name_len; + long argc = -1; + char *cbname = NULL; + pdo_dbh_t *dbh; + pdo_sqlite_db_handle *H; + int ret; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", + &func_name, &func_name_len, &callback, &argc)) { + RETURN_FALSE; + } + + dbh = zend_object_store_get_object(getThis() TSRMLS_CC); + + if (dbh->is_persistent) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "wont work on persistent handles"); + RETURN_FALSE; + } + + if (!zend_is_callable(callback, 0, &cbname)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname); + efree(cbname); + RETURN_FALSE; + } + efree(cbname); + + H = (pdo_sqlite_db_handle *)dbh->driver_data; + + func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func)); + + ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8, + func, php_sqlite3_func_callback, NULL, NULL); + + if (ret == SQLITE_OK) { + func->funcname = estrdup(func_name); + + MAKE_STD_ZVAL(func->func); + *(func->func) = *callback; + zval_copy_ctor(func->func); + + func->argc = argc; + + func->next = H->funcs; + H->funcs = func; + + RETURN_TRUE; + } + + efree(func); + RETURN_FALSE; +} +/* }}} */ + static function_entry dbh_methods[] = { - PHP_FE(sqlite_create_function, NULL) + PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; static function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC) { + printf("get_driver_methods\n"); switch (kind) { case PDO_DBH_DRIVER_METHOD_KIND_DBH: return dbh_methods;
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php