diff options
| author | Wez Furlong <wez@php.net> | 2005-06-10 02:50:37 +0000 | 
|---|---|---|
| committer | Wez Furlong <wez@php.net> | 2005-06-10 02:50:37 +0000 | 
| commit | be76bd5278ff3c9b772df6acc9a9623f6fafe199 (patch) | |
| tree | de5c42984a03eb9320f9a07351944bfe40801c88 /ext/pdo_sqlite/sqlite_driver.c | |
| parent | 648522ab980a446e231d0fa60bd0b4ae6437fd67 (diff) | |
| download | php-git-be76bd5278ff3c9b772df6acc9a9623f6fafe199.tar.gz | |
work in progress on UDF.
Something is hokey in HEAD, checking it in to try it on another box.
Diffstat (limited to 'ext/pdo_sqlite/sqlite_driver.c')
| -rw-r--r-- | ext/pdo_sqlite/sqlite_driver.c | 190 | 
1 files changed, 187 insertions, 3 deletions
diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 3fe9426e3c..41bf177089 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -96,11 +96,44 @@ static int pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *i  	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 @@ static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)  	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)  { -	/* TODO: implement this stuff */ +	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) +{ +	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;  | 
