Skip to content

Commit

Permalink
Add a few callable method parameter types to ext/sqlite3
Browse files Browse the repository at this point in the history
Closes GH-5988
  • Loading branch information
kocsismate committed Aug 14, 2020
1 parent ce38d3a commit d721615
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 67 deletions.
51 changes: 13 additions & 38 deletions ext/sqlite3/sqlite3.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,12 +952,13 @@ PHP_METHOD(SQLite3, createFunction)
php_sqlite3_func *func;
char *sql_func;
size_t sql_func_len;
zval *callback_func;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zend_long sql_func_num_args = -1;
zend_long flags = 0;
db_obj = Z_SQLITE3_DB_P(object);

if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|ll", &sql_func, &sql_func_len, &callback_func, &sql_func_num_args, &flags) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sf|ll", &sql_func, &sql_func_len, &fci, &fcc, &sql_func_num_args, &flags) == FAILURE) {
RETURN_THROWS();
}

Expand All @@ -967,19 +968,12 @@ PHP_METHOD(SQLite3, createFunction)
RETURN_FALSE;
}

if (!zend_is_callable(callback_func, 0, NULL)) {
zend_string *callback_name = zend_get_callable_name(callback_func);
php_sqlite3_error(db_obj, "Not a valid callback function %s", ZSTR_VAL(callback_name));
zend_string_release_ex(callback_name, 0);
RETURN_FALSE;
}

func = (php_sqlite3_func *)ecalloc(1, sizeof(*func));

if (sqlite3_create_function(db_obj->db, sql_func, sql_func_num_args, flags | SQLITE_UTF8, func, php_sqlite3_callback_func, NULL, NULL) == SQLITE_OK) {
func->func_name = estrdup(sql_func);

ZVAL_COPY(&func->func, callback_func);
ZVAL_COPY(&func->func, &fci.function_name);

func->argc = sql_func_num_args;
func->next = db_obj->funcs;
Expand All @@ -1001,11 +995,12 @@ PHP_METHOD(SQLite3, createAggregate)
php_sqlite3_func *func;
char *sql_func;
size_t sql_func_len;
zval *step_callback, *fini_callback;
zend_fcall_info step_fci, fini_fci;
zend_fcall_info_cache step_fcc, fini_fcc;
zend_long sql_func_num_args = -1;
db_obj = Z_SQLITE3_DB_P(object);

if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &sql_func, &sql_func_len, &step_callback, &fini_callback, &sql_func_num_args) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sff|l", &sql_func, &sql_func_len, &step_fci, &step_fcc, &fini_fci, &fini_fcc, &sql_func_num_args) == FAILURE) {
RETURN_THROWS();
}

Expand All @@ -1015,27 +1010,13 @@ PHP_METHOD(SQLite3, createAggregate)
RETURN_FALSE;
}

if (!zend_is_callable(step_callback, 0, NULL)) {
zend_string *callback_name = zend_get_callable_name(step_callback);
php_sqlite3_error(db_obj, "Not a valid callback function %s", ZSTR_VAL(callback_name));
zend_string_release_ex(callback_name, 0);
RETURN_FALSE;
}

if (!zend_is_callable(fini_callback, 0, NULL)) {
zend_string *callback_name = zend_get_callable_name(fini_callback);
php_sqlite3_error(db_obj, "Not a valid callback function %s", ZSTR_VAL(callback_name));
zend_string_release_ex(callback_name, 0);
RETURN_FALSE;
}

func = (php_sqlite3_func *)ecalloc(1, sizeof(*func));

if (sqlite3_create_function(db_obj->db, sql_func, sql_func_num_args, SQLITE_UTF8, func, NULL, php_sqlite3_callback_step, php_sqlite3_callback_final) == SQLITE_OK) {
func->func_name = estrdup(sql_func);

ZVAL_COPY(&func->step, step_callback);
ZVAL_COPY(&func->fini, fini_callback);
ZVAL_COPY(&func->step, &step_fci.function_name);
ZVAL_COPY(&func->fini, &fini_fci.function_name);

func->argc = sql_func_num_args;
func->next = db_obj->funcs;
Expand All @@ -1057,10 +1038,11 @@ PHP_METHOD(SQLite3, createCollation)
php_sqlite3_collation *collation;
char *collation_name;
size_t collation_name_len;
zval *callback_func;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
db_obj = Z_SQLITE3_DB_P(object);

if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &collation_name, &collation_name_len, &callback_func) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sf", &collation_name, &collation_name_len, &fci, &fcc) == FAILURE) {
RETURN_THROWS();
}

Expand All @@ -1070,18 +1052,11 @@ PHP_METHOD(SQLite3, createCollation)
RETURN_FALSE;
}

if (!zend_is_callable(callback_func, 0, NULL)) {
zend_string *callback_name = zend_get_callable_name(callback_func);
php_sqlite3_error(db_obj, "Not a valid callback function %s", ZSTR_VAL(callback_name));
zend_string_release_ex(callback_name, 0);
RETURN_FALSE;
}

collation = (php_sqlite3_collation *)ecalloc(1, sizeof(*collation));
if (sqlite3_create_collation(db_obj->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_callback_compare) == SQLITE_OK) {
collation->collation_name = estrdup(collation_name);

ZVAL_COPY(&collation->cmp_func, callback_func);
ZVAL_COPY(&collation->cmp_func, &fci.function_name);

collation->next = db_obj->collations;
db_obj->collations = collation;
Expand Down
26 changes: 8 additions & 18 deletions ext/sqlite3/sqlite3.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,14 @@ public function query(string $query) {}
/** @return mixed */
public function querySingle(string $query, bool $entire_row = false) {}

/**
* @param callable $callback
* @return bool
*/
public function createFunction(string $name, $callback, int $argument_count = -1, int $flags = 0) {}

/**
* @param callable $step_callback
* @param callable $final_callback
* @return bool
*/
public function createAggregate(string $name, $step_callback, $final_callback, int $argument_count = -1) {}

/**
* @param callable $callback
* @return bool
*/
public function createCollation(string $name, $callback) {}
/** @return bool */
public function createFunction(string $name, callable $callback, int $argument_count = -1, int $flags = 0) {}

/** @return bool */
public function createAggregate(string $name, callable $step_callback, callable $final_callback, int $argument_count = -1) {}

/** @return bool */
public function createCollation(string $name, callable $callback) {}

/** @return resource|false */
public function openBlob(string $table, string $column, int $rowid, string $dbname = "main", int $flags = SQLITE3_OPEN_READONLY) {}
Expand Down
10 changes: 5 additions & 5 deletions ext/sqlite3/sqlite3_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: cc36f3299089a453fac76179377b68647c33786c */
* Stub hash: d40496bbba4787b192a58896a9ca4858dc59dc76 */

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
Expand Down Expand Up @@ -61,21 +61,21 @@ ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3_createFunction, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0)
ZEND_ARG_INFO(0, callback)
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, argument_count, IS_LONG, 0, "-1")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3_createAggregate, 0, 0, 3)
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0)
ZEND_ARG_INFO(0, step_callback)
ZEND_ARG_INFO(0, final_callback)
ZEND_ARG_TYPE_INFO(0, step_callback, IS_CALLABLE, 0)
ZEND_ARG_TYPE_INFO(0, final_callback, IS_CALLABLE, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, argument_count, IS_LONG, 0, "-1")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3_createCollation, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0)
ZEND_ARG_INFO(0, callback)
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SQLite3_openBlob, 0, 0, 3)
Expand Down
21 changes: 15 additions & 6 deletions ext/sqlite3/tests/sqlite3_33_createAggregate_notcallable.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,26 @@ function aggregate_final ($var) { return $var; }

$db = new SQLite3(':memory:');

$db->createAggregate ('TESTAGGREGATE', 'aggregate_test_step', 'aggregate_final');
$db->createAggregate ('TESTAGGREGATE2', 'aggregate_step', 'aggregate_test_final');
try {
$db->createAggregate('TESTAGGREGATE', 'aggregate_test_step', 'aggregate_final');
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}

try {
$db->createAggregate('TESTAGGREGATE2', 'aggregate_step', 'aggregate_test_final');
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}

var_dump($db->createAggregate ('TESTAGGREGATE3', 'aggregate_step', 'aggregate_final'));

$db->close();

echo "Done"
?>
--EXPECTF--
Warning: SQLite3::createAggregate(): Not a valid callback function aggregate_test_step in %s on line %d

Warning: SQLite3::createAggregate(): Not a valid callback function aggregate_test_final in %s on line %d
--EXPECT--
SQLite3::createAggregate(): Argument #2 ($step_callback) must be a valid callback, function "aggregate_test_step" not found or invalid function name
SQLite3::createAggregate(): Argument #3 ($final_callback) must be a valid callback, function "aggregate_test_final" not found or invalid function name
bool(true)
Done

0 comments on commit d721615

Please sign in to comment.