Skip to content

Commit ee2506c

Browse files
committed
Fix #80027 Terrible performance using $query->fetch on queries with many bind parameters
Added new flags that allow skipping param_evt(s) that are not used by drivers, in a backwards and forward compatible manner. Updated the pgsql, mysql, sqlite and oci drivers to properly use the new flags. I've left out pdo_dblib, which doesn't have a param_hook, and pdo_firebird, which seems to be using PARAM_EVT_NORMALIZE in a wrong context (param type vs event type).
1 parent ad97739 commit ee2506c

File tree

7 files changed

+29
-2
lines changed

7 files changed

+29
-2
lines changed

ext/pdo/pdo_stmt.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ static int dispatch_param_event(pdo_stmt_t *stmt, enum pdo_param_event event_typ
9292
struct pdo_bound_param_data *param;
9393
HashTable *ht;
9494

95+
if (stmt->dbh->skip_param_evt & (1 << event_type)) {
96+
return 1;
97+
}
98+
9599
if (!stmt->methods->param_hook) {
96100
return 1;
97101
}

ext/pdo/php_pdo_driver.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,12 @@ struct _pdo_dbh_t {
466466
/* when set, convert int/floats to strings */
467467
unsigned stringify:1;
468468

469+
/* bitmap for pdo_param_event(s) to skip in dispatch_param_event */
470+
unsigned skip_param_evt:7;
471+
469472
/* the sum of the number of bits here and the bit fields preceding should
470473
* equal 32 */
471-
unsigned _reserved_flags:21;
474+
unsigned _reserved_flags:14;
472475

473476
/* data source string used to open this handle */
474477
const char *data_source;

ext/pdo_mysql/mysql_driver.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,13 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
617617

618618
dbh->driver_data = H;
619619

620+
dbh->skip_param_evt =
621+
1 << PDO_PARAM_EVT_FREE |
622+
1 << PDO_PARAM_EVT_EXEC_POST |
623+
1 << PDO_PARAM_EVT_FETCH_PRE |
624+
1 << PDO_PARAM_EVT_FETCH_POST |
625+
1 << PDO_PARAM_EVT_NORMALIZE;
626+
620627
#ifndef PDO_USE_MYSQLND
621628
H->max_buffer_size = 1024*1024;
622629
#endif

ext/pdo_oci/oci_driver.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,11 @@ static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ *
724724
H = pecalloc(1, sizeof(*H), dbh->is_persistent);
725725
dbh->driver_data = H;
726726

727+
dbh->skip_param_evt =
728+
1 << PDO_PARAM_EVT_FETCH_PRE |
729+
1 << PDO_PARAM_EVT_FETCH_POST |
730+
1 << PDO_PARAM_EVT_NORMALIZE;
731+
727732
H->prefetch = PDO_OCI_PREFETCH_DEFAULT;
728733

729734
/* allocate an environment */

ext/pdo_pgsql/pgsql_driver.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,11 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{
11921192
H = pecalloc(1, sizeof(pdo_pgsql_db_handle), dbh->is_persistent);
11931193
dbh->driver_data = H;
11941194

1195+
dbh->skip_param_evt =
1196+
1 << PDO_PARAM_EVT_EXEC_POST |
1197+
1 << PDO_PARAM_EVT_FETCH_PRE |
1198+
1 << PDO_PARAM_EVT_FETCH_POST;
1199+
11951200
H->einfo.errcode = 0;
11961201
H->einfo.errmsg = NULL;
11971202

ext/pdo_pgsql/pgsql_statement.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *
397397
}
398398
break;
399399
}
400-
} else if (param->is_param) {
400+
} else if (param->is_param && event_type == PDO_PARAM_EVT_NORMALIZE) {
401401
/* We need to manually convert to a pg native boolean value */
402402
if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL &&
403403
((param->param_type & PDO_PARAM_INPUT_OUTPUT) != PDO_PARAM_INPUT_OUTPUT)) {

ext/pdo_sqlite/sqlite_driver.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,9 @@ static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{
773773
H->einfo.errmsg = NULL;
774774
dbh->driver_data = H;
775775

776+
/* skip all but this one param event */
777+
dbh->skip_param_evt = 0x7F ^ (1 << PDO_PARAM_EVT_EXEC_PRE);
778+
776779
filename = make_filename_safe(dbh->data_source);
777780

778781
if (!filename) {

0 commit comments

Comments
 (0)