]> granicus.if.org Git - php/commitdiff
Implement sqlite_create_function(), which allows binding of php functions by
authorWez Furlong <wez@php.net>
Sun, 20 Apr 2003 13:31:36 +0000 (13:31 +0000)
committerWez Furlong <wez@php.net>
Sun, 20 Apr 2003 13:31:36 +0000 (13:31 +0000)
name; this is a higher performance alternative to the generic php() SQL
function. (saves parsing the additional function call in the SQL and a call to
zend_is_callable on each function invocation).

Add test for sqlite_create_function().

Fixup proto for sqlite_create_aggregate().

Tweak package file and speling in header file.

ext/sqlite/package.xml
ext/sqlite/php_sqlite.h
ext/sqlite/sqlite.c
ext/sqlite/tests/sqlite_006.phpt [new file with mode: 0644]

index e659eedd981f5a936cea15d659e1e526bfdc8b08..073c7ceaa6cdf18107d179d85018156576a17183 100644 (file)
       <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"/>
index 8cf157af090946be9586b8f2761e2659752e9e74..d85ac4bc3e10ebeef72b6291b132fb1f90a1b895 100644 (file)
@@ -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)
index b8f1b61877f07369c7562863cc00754ed9c1927e..fb1e92238b1f81c4ce499528dd71d3b002659c49 100644 (file)
@@ -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 (file)
index 0000000..e946f2d
--- /dev/null
@@ -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!