Handle column count change in PDO MySQL

This has been fixed for PDO SQlite by GH-4313, however the same
issue also applied to PDO MySQL.

Move the column count setting function into the main PDO layer
(and export it) and then use it in both PDO SQLite and PDO MySQL.
This commit is contained in:
Nikita Popov 2020-12-08 16:37:00 +01:00
parent 713ef8511b
commit bfa69d27bc
5 changed files with 108 additions and 77 deletions

View file

@ -39,46 +39,6 @@ static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt)
return 1;
}
/**
* Change the column count on the statement.
*
* Since PHP 7.2 sqlite3_prepare_v2 is used which auto recompile prepared statement on schema change.
* Instead of raise an error on schema change, the result set will change, and the statement's columns must be updated.
*
* See bug #78192
*/
static void pdo_sqlite_stmt_set_column_count(pdo_stmt_t *stmt, int new_count)
{
/* Columns not yet "described" */
if (!stmt->columns) {
stmt->column_count = new_count;
return;
}
/*
* The column count has not changed : no need to reload columns description
* Note: Do not handle attribute name change, without column count change
*/
if (new_count == stmt->column_count) {
return;
}
/* Free previous columns to force reload description */
int i;
for (i = 0; i < stmt->column_count; i++) {
if (stmt->columns[i].name) {
zend_string_release(stmt->columns[i].name);
stmt->columns[i].name = NULL;
}
}
efree(stmt->columns);
stmt->columns = NULL;
stmt->column_count = new_count;
}
static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt)
{
pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
@ -91,11 +51,11 @@ static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt)
switch (sqlite3_step(S->stmt)) {
case SQLITE_ROW:
S->pre_fetched = 1;
pdo_sqlite_stmt_set_column_count(stmt, sqlite3_data_count(S->stmt));
php_pdo_stmt_set_column_count(stmt, sqlite3_data_count(S->stmt));
return 1;
case SQLITE_DONE:
pdo_sqlite_stmt_set_column_count(stmt, sqlite3_column_count(S->stmt));
php_pdo_stmt_set_column_count(stmt, sqlite3_column_count(S->stmt));
stmt->row_count = sqlite3_changes(S->H->db);
sqlite3_reset(S->stmt);
S->done = 1;