diff options
-rw-r--r-- | ext/sqlite/package.xml | 6 | ||||
-rw-r--r-- | ext/sqlite/php_sqlite.h | 3 | ||||
-rw-r--r-- | ext/sqlite/sqlite.c | 107 | ||||
-rw-r--r-- | ext/sqlite/tests/sqlite_006.phpt | 50 |
4 files changed, 161 insertions, 5 deletions
diff --git a/ext/sqlite/package.xml b/ext/sqlite/package.xml index e659eedd98..073c7ceaa6 100644 --- a/ext/sqlite/package.xml +++ b/ext/sqlite/package.xml @@ -50,7 +50,11 @@ <file role="doc" name="README"/> <file role="doc" name="TODO"/> <file role="doc" name="sqlite.php"/> - <file role="test" name="tests/001.phpt"/> + <file role="test" name="tests/sqlite_001.phpt"/> + <file role="test" name="tests/sqlite_002.phpt"/> + <file role="test" name="tests/sqlite_003.phpt"/> + <file role="test" name="tests/sqlite_004.phpt"/> + <file role="test" name="tests/blankdb.inc"/> <dir name="libsqlite"> <file role="doc" name="README"/> diff --git a/ext/sqlite/php_sqlite.h b/ext/sqlite/php_sqlite.h index 8cf157af09..d85ac4bc3e 100644 --- a/ext/sqlite/php_sqlite.h +++ b/ext/sqlite/php_sqlite.h @@ -13,7 +13,7 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Wez Furlong <wez@thebrainroom.com> | - | Tal Peer <tal@php.net | + | Tal Peer <tal@php.net> | +----------------------------------------------------------------------+ $Id$ @@ -67,6 +67,7 @@ PHP_FUNCTION(sqlite_last_error); PHP_FUNCTION(sqlite_error_string); PHP_FUNCTION(sqlite_create_aggregate); +PHP_FUNCTION(sqlite_create_function); #ifdef ZTS #define SQLITE_G(v) TSRMG(sqlite_globals_id, zend_sqlite_globals *, v) diff --git a/ext/sqlite/sqlite.c b/ext/sqlite/sqlite.c index b8f1b61877..fb1e92238b 100644 --- a/ext/sqlite/sqlite.c +++ b/ext/sqlite/sqlite.c @@ -93,6 +93,7 @@ function_entry sqlite_functions[] = { PHP_FE(sqlite_error_string, NULL) PHP_FE(sqlite_unbuffered_query, NULL) PHP_FE(sqlite_create_aggregate, NULL) + PHP_FE(sqlite_create_function, NULL) {NULL, NULL, NULL} }; @@ -191,7 +192,7 @@ PHP_RSHUTDOWN_FUNCTION(sqlite) } /* {{{ PHP Function interface */ -static void php_sqlite_function_callback(sqlite_func *func, int argc, const char **argv) +static void php_sqlite_generic_function_callback(sqlite_func *func, int argc, const char **argv) { zval *retval = NULL; zval ***zargs; @@ -273,6 +274,70 @@ static void php_sqlite_function_callback(sqlite_func *func, int argc, const char } /* }}} */ +static void php_sqlite_function_callback(sqlite_func *func, int argc, const char **argv) +{ + zval *retval = NULL; + zval ***zargs; + int i, res; + char *errbuf=NULL; + struct php_sqlite_agg_functions *funcs = sqlite_user_data(func); + TSRMLS_FETCH(); + + if (argc > 0) { + zargs = (zval ***)emalloc(argc * sizeof(zval **)); + + for (i = 0; i < argc; i++) { + zargs[i] = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*zargs[i]); + ZVAL_STRING(*zargs[i], (char*)argv[i], 1); + } + } + + res = call_user_function_ex(EG(function_table), + NULL, + funcs->step, + &retval, + argc, + zargs, + 0, NULL TSRMLS_CC); + + if (res == SUCCESS) { + if (retval == NULL) { + sqlite_set_result_string(func, NULL, 0); + } else { + switch (Z_TYPE_P(retval)) { + case IS_STRING: + sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval)); + break; + case IS_LONG: + case IS_BOOL: + sqlite_set_result_int(func, Z_LVAL_P(retval)); + break; + case IS_DOUBLE: + sqlite_set_result_double(func, Z_DVAL_P(retval)); + break; + case IS_NULL: + default: + sqlite_set_result_string(func, NULL, 0); + } + } + } else { + sqlite_set_result_error(func, "call_user_function_ex failed", -1); + } + + if (retval) { + zval_ptr_dtor(&retval); + } + + if (zargs) { + for (i = 0; i < argc; i++) { + zval_ptr_dtor(zargs[i]); + efree(zargs[i]); + } + efree(zargs); + } +} + static void php_sqlite_agg_step_function_callback(sqlite_func *func, int argc, const char **argv) { zval *retval = NULL; @@ -488,7 +553,7 @@ static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *per db->db = sdb; /* register the PHP functions */ - sqlite_create_function(sdb, "php", -1, php_sqlite_function_callback, 0); + sqlite_create_function(sdb, "php", -1, php_sqlite_generic_function_callback, 0); /* set default busy handler; keep retrying up until 1/2 second has passed, * then fail with a busy status code */ @@ -1127,7 +1192,7 @@ PHP_FUNCTION(sqlite_error_string) } /* }}} */ -/* {{{ proto bool sqlite_create_aggregate(string funcname, string step_f, string finalize_f[, long num_args]) +/* {{{ proto bool sqlite_create_aggregate(resource db, string funcname, mixed step_func, mixed finalize_func[, long num_args]) Registers an aggregated function for queries*/ PHP_FUNCTION(sqlite_create_aggregate) { @@ -1173,3 +1238,39 @@ PHP_FUNCTION(sqlite_create_aggregate) sqlite_create_aggregate(db->db, funcname, num_args, php_sqlite_agg_step_function_callback, php_sqlite_agg_fini_function_callback, funcs); } /* }}} */ + +/* {{{ proto bool sqlite_create_function(resource db, string funcname, mixed callback[, long num_args]) + Registers a "regular" function for queries */ +PHP_FUNCTION(sqlite_create_function) +{ + char *funcname = NULL; + long funcname_len; + zval *zcall, *zdb; + struct php_sqlite_db *db; + struct php_sqlite_agg_functions *funcs; + char *callable = NULL; + long num_args = -1; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args) == FAILURE) { + return; + } + + if (!zend_is_callable(zcall, 0, &callable)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "step function `%s' is not callable", callable); + efree(callable); + return; + } + efree(callable); + + DB_FROM_ZVAL(db, &zdb); + + /* TODO: this needs to be cleaned up */ + funcs = (struct php_sqlite_agg_functions *)emalloc(sizeof(*funcs)); + + MAKE_STD_ZVAL(funcs->step); + *(funcs->step) = *zcall; + zval_copy_ctor(funcs->step); + + sqlite_create_function(db->db, funcname, num_args, php_sqlite_function_callback, funcs); +} +/* }}} */ diff --git a/ext/sqlite/tests/sqlite_006.phpt b/ext/sqlite/tests/sqlite_006.phpt new file mode 100644 index 0000000000..e946f2d30b --- /dev/null +++ b/ext/sqlite/tests/sqlite_006.phpt @@ -0,0 +1,50 @@ +--TEST-- +sqlite: regular functions +--SKIPIF-- +<?php # vim:ft=php +if (!extension_loaded("sqlite")) print "skip"; ?> +--FILE-- +<?php +include "blankdb.inc"; + +$data = array( + array("one", "uno"), + array("two", "dos"), + array("three", "tres"), + ); + +sqlite_query("CREATE TABLE strings(a,b)", $db); + +function implode_args() +{ + $args = func_get_args(); + $sep = array_shift($args); + return implode($sep, $args); +} + +foreach ($data as $row) { + sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($row[0]) . "','" . sqlite_escape_string($row[1]) . "')", $db); +} + +sqlite_create_function($db, "implode", "implode_args"); + +$r = sqlite_query("SELECT implode('-', a, b) from strings", $db); +while ($row = sqlite_fetch_array($r, SQLITE_NUM)) { + var_dump($row); +} +echo "DONE!\n"; +?> +--EXPECT-- +array(1) { + [0]=> + string(7) "one-uno" +} +array(1) { + [0]=> + string(7) "two-dos" +} +array(1) { + [0]=> + string(10) "three-tres" +} +DONE! |