summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite_driver.c
diff options
context:
space:
mode:
authorRasmus Lerdorf <rasmus@php.net>2012-01-29 04:22:23 +0000
committerRasmus Lerdorf <rasmus@php.net>2012-01-29 04:22:23 +0000
commitabff96d02ed818fcd5cddc06d61e9afd3c14b3ac (patch)
treecc041143c93d127b398ef1367b4c73c24296daf3 /ext/pdo_sqlite/sqlite_driver.c
parent191cc014be09ce107dbf1e74d5607be2d4139a4b (diff)
downloadphp-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.c125
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
};