Skip to content

Fixed DOUBLE EXECUTION OF QUERIES when executing first SQLite3Result-… #8415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ext/sqlite3/php_sqlite3_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ struct _php_sqlite3_result_object {
php_sqlite3_db_object *db_obj;
php_sqlite3_stmt *stmt_obj;
zval stmt_obj_zval;

/* START */
/* Store the last step error code from Sqlite3::query(), SQlite3Stmt::execute() to passe it to SQLite3Result::fetchArray() */
int last_error;
/* END */

/* Cache of column names to speed up repeated fetchArray(SQLITE3_ASSOC) calls.
* Cache is cleared on reset() and finalize() calls. */
Expand Down
37 changes: 34 additions & 3 deletions ext/sqlite3/sqlite3.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,10 @@ PHP_METHOD(SQLite3, query)
ZVAL_OBJ(&result->stmt_obj_zval, Z_OBJ(stmt));

return_code = sqlite3_step(result->stmt_obj->stmt);
/* START */
/* Copy step error code in result struct to pass it to SQLite3Result::fetcharray() */
result->last_error = return_code;
/* END */

switch (return_code) {
case SQLITE_ROW: /* Valid Row */
Expand All @@ -601,7 +605,11 @@ PHP_METHOD(SQLite3, query)
free_item->stmt_obj = stmt_obj;
free_item->stmt_obj_zval = stmt;
zend_llist_add_element(&(db_obj->free_list), &free_item);
sqlite3_reset(result->stmt_obj->stmt);
/* START */
/* Main problem. This resets the query and forces SQLite3Result::fetcharray() to execute it again */
/* So we have to disable it to avoid a double execution of the query */
/*sqlite3_reset(result->stmt_obj->stmt);*/
/* END */
break;
}
default:
Expand Down Expand Up @@ -1787,7 +1795,10 @@ PHP_METHOD(SQLite3Stmt, execute)
case SQLITE_ROW: /* Valid Row */
case SQLITE_DONE: /* Valid but no results */
{
sqlite3_reset(stmt_obj->stmt);
/* START */
/* Main problem. This resets the query and forces SQLite3Result::fetcharray() to execute it again */
/*sqlite3_reset(stmt_obj->stmt);*/
/* END */
object_init_ex(return_value, php_sqlite3_result_entry);
result = Z_SQLITE3_RESULT_P(return_value);

Expand All @@ -1796,6 +1807,10 @@ PHP_METHOD(SQLite3Stmt, execute)
result->stmt_obj = stmt_obj;
result->column_names = NULL;
result->column_count = -1;
/* START */
/* Do not reset the query just pass the step error code in 'result' struct to SQLite3Result::fetcharray() */
result->last_error = return_code;
/* END */
ZVAL_OBJ_COPY(&result->stmt_obj_zval, Z_OBJ_P(object));

break;
Expand Down Expand Up @@ -1941,7 +1956,17 @@ PHP_METHOD(SQLite3Result, fetchArray)

SQLITE3_CHECK_INITIALIZED(result_obj->db_obj, result_obj->stmt_obj->initialised, SQLite3Result)

ret = sqlite3_step(result_obj->stmt_obj->stmt);
/* START */
/* Get result code stored in 'result_obj' struct, initialized by Sqlite3::query(), SQLite3Stmt::execute() */
/* The first time we call SQLite3Result->fetchArray(), skip step and process the step result of Sqlite3::query() or SQLite3Stmt::execute() */
/* The first time we call SQLite3Result->fetchArray(), the step result stored in 'last_error' can only be SQLITE_ROW or SQLITE_DONE */
/* From the second call to SQLite3Result->fetchArray() onwards, 'last_error' will be -1 and therefore step will be executed */
ret = result_obj->last_error;
if (ret == -1) {
ret = sqlite3_step(result_obj->stmt_obj->stmt);
}
/* END */

switch (ret) {
case SQLITE_ROW:
/* If there was no return value then just skip fetching */
Expand Down Expand Up @@ -1985,6 +2010,12 @@ PHP_METHOD(SQLite3Result, fetchArray)
zend_symtable_add_new(Z_ARR_P(return_value), result_obj->column_names[i], &data);
}
}

/* START */
/* Intialize to -1 so on the second call to SQLite3Result->fetchArray() onwards, step is executed */
result_obj->last_error = -1;
/* END */

break;

case SQLITE_DONE:
Expand Down