rasmus                                   Sun, 29 Jan 2012 04:22:23 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=322916

Log:
createCollation() for pdo_sqlite as well
Closes bug #55226

Bug: https://bugs.php.net/55226 (Open) Support creating collations in SQLite
      
Changed paths:
    U   php/php-src/branches/PHP_5_3/ext/pdo_sqlite/php_pdo_sqlite_int.h
    U   php/php-src/branches/PHP_5_3/ext/pdo_sqlite/sqlite_driver.c
    A   
php/php-src/branches/PHP_5_3/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt
    U   php/php-src/branches/PHP_5_4/ext/pdo_sqlite/php_pdo_sqlite_int.h
    U   php/php-src/branches/PHP_5_4/ext/pdo_sqlite/sqlite_driver.c
    A   
php/php-src/branches/PHP_5_4/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt
    U   php/php-src/trunk/ext/pdo_sqlite/php_pdo_sqlite_int.h
    U   php/php-src/trunk/ext/pdo_sqlite/sqlite_driver.c
    A   php/php-src/trunk/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt

Modified: php/php-src/branches/PHP_5_3/ext/pdo_sqlite/php_pdo_sqlite_int.h
===================================================================
--- php/php-src/branches/PHP_5_3/ext/pdo_sqlite/php_pdo_sqlite_int.h	2012-01-29 04:20:50 UTC (rev 322915)
+++ php/php-src/branches/PHP_5_3/ext/pdo_sqlite/php_pdo_sqlite_int.h	2012-01-29 04:22:23 UTC (rev 322916)
@@ -46,10 +46,19 @@
 	struct pdo_sqlite_fci afunc, astep, afini;
 };

+struct pdo_sqlite_collation {
+	struct pdo_sqlite_collation *next;
+
+	const char *name;
+	zval *callback;
+	struct pdo_sqlite_fci fc;
+};
+
 typedef struct {
 	sqlite3 *db;
 	pdo_sqlite_error_info einfo;
 	struct pdo_sqlite_func *funcs;
+	struct pdo_sqlite_collation *collations;
 } pdo_sqlite_db_handle;

 typedef struct {

Modified: php/php-src/branches/PHP_5_3/ext/pdo_sqlite/sqlite_driver.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/pdo_sqlite/sqlite_driver.c	2012-01-29 04:20:50 UTC (rev 322915)
+++ php/php-src/branches/PHP_5_3/ext/pdo_sqlite/sqlite_driver.c	2012-01-29 04:22:23 UTC (rev 322916)
@@ -129,6 +129,28 @@
 		}
 		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 @@
 	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 @@
 	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
 };


Added: php/php-src/branches/PHP_5_3/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt	2012-01-29 04:22:23 UTC (rev 322916)
@@ -0,0 +1,38 @@
+--TEST--
+PDO_sqlite: Testing sqliteCreateCollation()
+--SKIPIF--
+<?php if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ?>
+--FILE--
+<?php
+
+$db = new pdo('sqlite::memory:');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+$db->query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)');
+
+$db->query('INSERT INTO foobar VALUES (NULL, "1")');
+$db->query('INSERT INTO foobar VALUES (NULL, "2")');
+$db->query('INSERT INTO foobar VALUES (NULL, "10")');
+
+$db->sqliteCreateCollation('MYCOLLATE', function($a, $b) { return strnatcmp($a, $b); });
+
+$result = $db->query('SELECT name FROM foobar ORDER BY name COLLATE MYCOLLATE');
+foreach ($result as $row) {
+	echo $row['name'] . "\n";
+}
+
+$result = $db->query('SELECT name FROM foobar ORDER BY name');
+foreach ($result as $row) {
+  echo $row['name'] . "\n";
+}
+
+$db->query('DROP TABLE foobar');
+
+?>
+--EXPECTF--
+1
+2
+10
+1
+10
+2

Modified: php/php-src/branches/PHP_5_4/ext/pdo_sqlite/php_pdo_sqlite_int.h
===================================================================
--- php/php-src/branches/PHP_5_4/ext/pdo_sqlite/php_pdo_sqlite_int.h	2012-01-29 04:20:50 UTC (rev 322915)
+++ php/php-src/branches/PHP_5_4/ext/pdo_sqlite/php_pdo_sqlite_int.h	2012-01-29 04:22:23 UTC (rev 322916)
@@ -46,10 +46,19 @@
 	struct pdo_sqlite_fci afunc, astep, afini;
 };

+struct pdo_sqlite_collation {
+	struct pdo_sqlite_collation *next;
+
+	const char *name;
+	zval *callback;
+	struct pdo_sqlite_fci fc;
+};
+
 typedef struct {
 	sqlite3 *db;
 	pdo_sqlite_error_info einfo;
 	struct pdo_sqlite_func *funcs;
+	struct pdo_sqlite_collation *collations;
 } pdo_sqlite_db_handle;

 typedef struct {

Modified: php/php-src/branches/PHP_5_4/ext/pdo_sqlite/sqlite_driver.c
===================================================================
--- php/php-src/branches/PHP_5_4/ext/pdo_sqlite/sqlite_driver.c	2012-01-29 04:20:50 UTC (rev 322915)
+++ php/php-src/branches/PHP_5_4/ext/pdo_sqlite/sqlite_driver.c	2012-01-29 04:22:23 UTC (rev 322916)
@@ -129,6 +129,28 @@
 		}
 		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 @@
 	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,62 @@
 	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
 };


Added: php/php-src/branches/PHP_5_4/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt	2012-01-29 04:22:23 UTC (rev 322916)
@@ -0,0 +1,38 @@
+--TEST--
+PDO_sqlite: Testing sqliteCreateCollation()
+--SKIPIF--
+<?php if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ?>
+--FILE--
+<?php
+
+$db = new pdo('sqlite::memory:');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+$db->query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)');
+
+$db->query('INSERT INTO foobar VALUES (NULL, "1")');
+$db->query('INSERT INTO foobar VALUES (NULL, "2")');
+$db->query('INSERT INTO foobar VALUES (NULL, "10")');
+
+$db->sqliteCreateCollation('MYCOLLATE', function($a, $b) { return strnatcmp($a, $b); });
+
+$result = $db->query('SELECT name FROM foobar ORDER BY name COLLATE MYCOLLATE');
+foreach ($result as $row) {
+	echo $row['name'] . "\n";
+}
+
+$result = $db->query('SELECT name FROM foobar ORDER BY name');
+foreach ($result as $row) {
+  echo $row['name'] . "\n";
+}
+
+$db->query('DROP TABLE foobar');
+
+?>
+--EXPECTF--
+1
+2
+10
+1
+10
+2

Modified: php/php-src/trunk/ext/pdo_sqlite/php_pdo_sqlite_int.h
===================================================================
--- php/php-src/trunk/ext/pdo_sqlite/php_pdo_sqlite_int.h	2012-01-29 04:20:50 UTC (rev 322915)
+++ php/php-src/trunk/ext/pdo_sqlite/php_pdo_sqlite_int.h	2012-01-29 04:22:23 UTC (rev 322916)
@@ -46,10 +46,19 @@
 	struct pdo_sqlite_fci afunc, astep, afini;
 };

+struct pdo_sqlite_collation {
+	struct pdo_sqlite_collation *next;
+
+	const char *name;
+	zval *callback;
+	struct pdo_sqlite_fci fc;
+};
+
 typedef struct {
 	sqlite3 *db;
 	pdo_sqlite_error_info einfo;
 	struct pdo_sqlite_func *funcs;
+	struct pdo_sqlite_collation *collations;
 } pdo_sqlite_db_handle;

 typedef struct {

Modified: php/php-src/trunk/ext/pdo_sqlite/sqlite_driver.c
===================================================================
--- php/php-src/trunk/ext/pdo_sqlite/sqlite_driver.c	2012-01-29 04:20:50 UTC (rev 322915)
+++ php/php-src/trunk/ext/pdo_sqlite/sqlite_driver.c	2012-01-29 04:22:23 UTC (rev 322916)
@@ -129,6 +129,28 @@
 		}
 		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 @@
 	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,62 @@
 	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
 };


Added: php/php-src/trunk/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt
===================================================================
--- php/php-src/trunk/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt	2012-01-29 04:22:23 UTC (rev 322916)
@@ -0,0 +1,38 @@
+--TEST--
+PDO_sqlite: Testing sqliteCreateCollation()
+--SKIPIF--
+<?php if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ?>
+--FILE--
+<?php
+
+$db = new pdo('sqlite::memory:');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+$db->query('CREATE TABLE IF NOT EXISTS foobar (id INT AUTO INCREMENT, name TEXT)');
+
+$db->query('INSERT INTO foobar VALUES (NULL, "1")');
+$db->query('INSERT INTO foobar VALUES (NULL, "2")');
+$db->query('INSERT INTO foobar VALUES (NULL, "10")');
+
+$db->sqliteCreateCollation('MYCOLLATE', function($a, $b) { return strnatcmp($a, $b); });
+
+$result = $db->query('SELECT name FROM foobar ORDER BY name COLLATE MYCOLLATE');
+foreach ($result as $row) {
+	echo $row['name'] . "\n";
+}
+
+$result = $db->query('SELECT name FROM foobar ORDER BY name');
+foreach ($result as $row) {
+  echo $row['name'] . "\n";
+}
+
+$db->query('DROP TABLE foobar');
+
+?>
+--EXPECTF--
+1
+2
+10
+1
+10
+2
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to