|
36 | 36 | #include "pgsql_driver_arginfo.h" |
37 | 37 |
|
38 | 38 | static bool pgsql_handle_in_transaction(pdo_dbh_t *dbh); |
| 39 | +void pgsql_stmt_finish(pdo_pgsql_stmt *S, int fin_mode); |
39 | 40 |
|
40 | 41 | static char * _pdo_pgsql_trim_message(const char *message, int persistent) |
41 | 42 | { |
@@ -109,6 +110,37 @@ int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char * |
109 | 110 | } |
110 | 111 | /* }}} */ |
111 | 112 |
|
| 113 | +static zend_always_inline void pgsql_finish_running_stmt(pdo_pgsql_db_handle *H) |
| 114 | +{ |
| 115 | + if (H->running_stmt) { |
| 116 | + pgsql_stmt_finish(H->running_stmt, 0); |
| 117 | + } |
| 118 | +} |
| 119 | + |
| 120 | +static zend_always_inline void pgsql_discard_running_stmt(pdo_pgsql_db_handle *H) |
| 121 | +{ |
| 122 | + if (H->running_stmt) { |
| 123 | + pgsql_stmt_finish(H->running_stmt, FIN_DISCARD); |
| 124 | + } |
| 125 | + |
| 126 | + PGresult *pgsql_result; |
| 127 | + bool first = true; |
| 128 | + while ((pgsql_result = PQgetResult(H->server))) { |
| 129 | + /* We should not arrive here, where libpq has a result to deliver without us |
| 130 | + * having registered a running statement: |
| 131 | + * every result discarding should go through the unified pgsql_stmt_finish, |
| 132 | + * but maybe there still is an internal query that we omitted to adapt. |
| 133 | + * So instead of asserting let's just emit an informational notice, |
| 134 | + * and consume anyway (results consumption is handle-wise, so we have no formal |
| 135 | + * need for the statement). */ |
| 136 | + if (first) { |
| 137 | + php_error_docref("ref.pgsql", E_NOTICE, "Internal error: unable to link a libpq result to consume, to its origin statement"); |
| 138 | + first = false; |
| 139 | + } |
| 140 | + PQclear(pgsql_result); |
| 141 | + } |
| 142 | +} |
| 143 | + |
112 | 144 | static void _pdo_pgsql_notice(void *context, const char *message) /* {{{ */ |
113 | 145 | { |
114 | 146 | pdo_dbh_t * dbh = (pdo_dbh_t *)context; |
@@ -355,6 +387,7 @@ static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) |
355 | 387 |
|
356 | 388 | bool in_trans = pgsql_handle_in_transaction(dbh); |
357 | 389 |
|
| 390 | + pgsql_finish_running_stmt(H); |
358 | 391 | if (!(res = PQexec(H->server, ZSTR_VAL(sql)))) { |
359 | 392 | /* fatal error */ |
360 | 393 | pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); |
@@ -430,6 +463,7 @@ static zend_string *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const zend_string * |
430 | 463 | PGresult *res; |
431 | 464 | ExecStatusType status; |
432 | 465 |
|
| 466 | + pgsql_finish_running_stmt(H); |
433 | 467 | if (name == NULL) { |
434 | 468 | res = PQexec(H->server, "SELECT LASTVAL()"); |
435 | 469 | } else { |
@@ -593,6 +627,7 @@ static bool pdo_pgsql_transaction_cmd(const char *cmd, pdo_dbh_t *dbh) |
593 | 627 | PGresult *res; |
594 | 628 | bool ret = true; |
595 | 629 |
|
| 630 | + pgsql_finish_running_stmt(H); |
596 | 631 | res = PQexec(H->server, cmd); |
597 | 632 |
|
598 | 633 | if (PQresultStatus(res) != PGRES_COMMAND_OK) { |
@@ -700,9 +735,8 @@ void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS) |
700 | 735 | /* Obtain db Handle */ |
701 | 736 | H = (pdo_pgsql_db_handle *)dbh->driver_data; |
702 | 737 |
|
703 | | - while ((pgsql_result = PQgetResult(H->server))) { |
704 | | - PQclear(pgsql_result); |
705 | | - } |
| 738 | + pgsql_discard_running_stmt(H); |
| 739 | + |
706 | 740 | pgsql_result = PQexec(H->server, query); |
707 | 741 |
|
708 | 742 | efree(query); |
@@ -824,9 +858,8 @@ void pgsqlCopyFromFile_internal(INTERNAL_FUNCTION_PARAMETERS) |
824 | 858 |
|
825 | 859 | H = (pdo_pgsql_db_handle *)dbh->driver_data; |
826 | 860 |
|
827 | | - while ((pgsql_result = PQgetResult(H->server))) { |
828 | | - PQclear(pgsql_result); |
829 | | - } |
| 861 | + pgsql_discard_running_stmt(H); |
| 862 | + |
830 | 863 | pgsql_result = PQexec(H->server, query); |
831 | 864 |
|
832 | 865 | efree(query); |
@@ -920,9 +953,7 @@ void pgsqlCopyToFile_internal(INTERNAL_FUNCTION_PARAMETERS) |
920 | 953 | RETURN_FALSE; |
921 | 954 | } |
922 | 955 |
|
923 | | - while ((pgsql_result = PQgetResult(H->server))) { |
924 | | - PQclear(pgsql_result); |
925 | | - } |
| 956 | + pgsql_discard_running_stmt(H); |
926 | 957 |
|
927 | 958 | /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */ |
928 | 959 | if (pg_fields) { |
@@ -1011,9 +1042,7 @@ void pgsqlCopyToArray_internal(INTERNAL_FUNCTION_PARAMETERS) |
1011 | 1042 |
|
1012 | 1043 | H = (pdo_pgsql_db_handle *)dbh->driver_data; |
1013 | 1044 |
|
1014 | | - while ((pgsql_result = PQgetResult(H->server))) { |
1015 | | - PQclear(pgsql_result); |
1016 | | - } |
| 1045 | + pgsql_discard_running_stmt(H); |
1017 | 1046 |
|
1018 | 1047 | /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */ |
1019 | 1048 | if (pg_fields) { |
|
0 commit comments