diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index cbfd55fc1aa6..a0c18018c193 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -256,6 +256,11 @@ static void pgsql_handle_closer(pdo_dbh_t *dbh) /* {{{ */ PQfinish(H->server); H->server = NULL; } + if (H->cached_table_name) { + H->cached_table_oid = InvalidOid; + efree(H->cached_table_name); + H->cached_table_name = NULL; + } if (H->einfo.errmsg) { pefree(H->einfo.errmsg, dbh->is_persistent); H->einfo.errmsg = NULL; @@ -1542,6 +1547,7 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ H->attached = 1; H->pgoid = -1; + H->cached_table_oid = InvalidOid; dbh->methods = &pgsql_methods; dbh->alloc_own_columns = 1; diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 2f0725534937..29f97a46fa7d 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -814,12 +814,29 @@ static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pd return 1; } -static zend_always_inline char * pdo_pgsql_translate_oid_to_table(Oid oid, PGconn *conn) +static zend_always_inline char * pdo_pgsql_translate_oid_to_table(Oid oid, pdo_pgsql_db_handle *H) { + PGconn *conn = H->server; char *table_name = NULL; PGresult *tmp_res; char *querystr = NULL; + if (oid == InvalidOid) { + /* InvalidOid is emitted when not selecting from a table (e.g. "SELECT 1"). No need of + * a database roundtrip. + */ + return NULL; + } + if (oid == H->cached_table_oid) { + return H->cached_table_name ? estrdup(H->cached_table_name) : NULL; + } + + if (H->cached_table_name) { + efree(H->cached_table_name); + H->cached_table_name = NULL; + H->cached_table_oid = InvalidOid; + } + spprintf(&querystr, 0, "SELECT RELNAME FROM PG_CLASS WHERE OID=%d", oid); if ((tmp_res = PQexec(conn, querystr)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) { @@ -836,6 +853,8 @@ static zend_always_inline char * pdo_pgsql_translate_oid_to_table(Oid oid, PGcon return 0; } + H->cached_table_oid = oid; + H->cached_table_name = estrdup(table_name); table_name = estrdup(table_name); PQclear(tmp_res); @@ -864,7 +883,7 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *r table_oid = PQftable(S->result, colno); add_assoc_long(return_value, "pgsql:table_oid", table_oid); - table_name = pdo_pgsql_translate_oid_to_table(table_oid, S->H->server); + table_name = pdo_pgsql_translate_oid_to_table(table_oid, S->H); if (table_name) { add_assoc_string(return_value, "table", table_name); efree(table_name); diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h index dc71d5ae7a5f..e609b9ef5ed8 100644 --- a/ext/pdo_pgsql/php_pdo_pgsql_int.h +++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h @@ -41,6 +41,8 @@ typedef struct { unsigned _reserved:31; pdo_pgsql_error_info einfo; Oid pgoid; + Oid cached_table_oid; + char *cached_table_name; unsigned int stmt_counter; bool emulate_prepares; bool disable_prepares;