diff options
author | Rasmus Lerdorf <rasmus@php.net> | 2012-01-29 04:22:23 +0000 |
---|---|---|
committer | Rasmus Lerdorf <rasmus@php.net> | 2012-01-29 04:22:23 +0000 |
commit | abff96d02ed818fcd5cddc06d61e9afd3c14b3ac (patch) | |
tree | cc041143c93d127b398ef1367b4c73c24296daf3 /ext/pdo_sqlite/sqlite_driver.c | |
parent | 191cc014be09ce107dbf1e74d5607be2d4139a4b (diff) | |
download | php-git-abff96d02ed818fcd5cddc06d61e9afd3c14b3ac.tar.gz |
createCollation() for pdo_sqlite as well
Closes bug #55226
Diffstat (limited to 'ext/pdo_sqlite/sqlite_driver.c')
-rw-r--r-- | ext/pdo_sqlite/sqlite_driver.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index bcbcd30354..5292f98371 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -129,6 +129,28 @@ static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC) } efree(func); } + + struct pdo_sqlite_collation *collation; + + while (H->collations) { + collation = H->collations; + H->collations = collation->next; + + if (H->db) { + /* delete the collation from the handle */ + sqlite3_create_collation(H->db, + collation->name, + SQLITE_UTF8, + collation, + NULL); + } + + efree((char*)collation->name); + if (collation->callback) { + zval_ptr_dtor(&collation->callback); + } + efree(collation); + } } static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */ @@ -457,6 +479,57 @@ static void php_sqlite3_func_final_callback(sqlite3_context *context) do_callback(&func->afini, func->fini, 0, NULL, context, 1 TSRMLS_CC); } +static int php_sqlite3_collation_callback(void *context, + int string1_len, const void *string1, + int string2_len, const void *string2) +{ + int ret; + zval *zstring1, *zstring2; + zval **zargs[2]; + zval *retval = NULL; + struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context; + TSRMLS_FETCH(); + + collation->fc.fci.size = sizeof(collation->fc.fci); + collation->fc.fci.function_table = EG(function_table); + collation->fc.fci.function_name = collation->callback; + collation->fc.fci.symbol_table = NULL; + collation->fc.fci.object_ptr = NULL; + collation->fc.fci.retval_ptr_ptr = &retval; + + // Prepare the arguments. + MAKE_STD_ZVAL(zstring1); + ZVAL_STRINGL(zstring1, (char *) string1, string1_len, 1); + zargs[0] = &zstring1; + MAKE_STD_ZVAL(zstring2); + ZVAL_STRINGL(zstring2, (char *) string2, string2_len, 1); + zargs[1] = &zstring2; + collation->fc.fci.param_count = 2; + collation->fc.fci.params = zargs; + + if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc TSRMLS_CC)) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback"); + } + else if (retval) { + if (Z_TYPE_P(retval) != IS_LONG) { + convert_to_long_ex(&retval); + } + ret = 0; + if (Z_LVAL_P(retval) > 0) { + ret = 1; + } + else if (Z_LVAL_P(retval) < 0) { + ret = -1; + } + zval_ptr_dtor(&retval); + } + + zval_ptr_dtor(zargs[0]); + zval_ptr_dtor(zargs[1]); + + return ret; +} + /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount]) Registers a UDF with the sqlite db handle */ static PHP_METHOD(SQLite, sqliteCreateFunction) @@ -590,9 +663,61 @@ static PHP_METHOD(SQLite, sqliteCreateAggregate) RETURN_FALSE; } /* }}} */ + +/* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback) + Registers a collation with the sqlite db handle */ +static PHP_METHOD(SQLite, sqliteCreateCollation) +{ + struct pdo_sqlite_collation *collation; + zval *callback; + char *collation_name; + int collation_name_len; + 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", + &collation_name, &collation_name_len, &callback)) { + RETURN_FALSE; + } + + dbh = zend_object_store_get_object(getThis() TSRMLS_CC); + PDO_CONSTRUCT_CHECK; + + if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) { + 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; + + collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation)); + + ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback); + if (ret == SQLITE_OK) { + collation->name = estrdup(collation_name); + + MAKE_STD_ZVAL(collation->callback); + MAKE_COPY_ZVAL(&callback, collation->callback); + + collation->next = H->collations; + H->collations = collation; + + RETURN_TRUE; + } + + efree(collation); + RETURN_FALSE; +} +/* }}} */ + static const zend_function_entry dbh_methods[] = { PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC) PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC) + PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC) PHP_FE_END }; |