|
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 | {
|
@@ -103,6 +104,37 @@ int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *
|
103 | 104 | }
|
104 | 105 | /* }}} */
|
105 | 106 |
|
| 107 | +static zend_always_inline void pgsql_finish_running_stmt(pdo_pgsql_db_handle *H) |
| 108 | +{ |
| 109 | + if (H->running_stmt) { |
| 110 | + pgsql_stmt_finish(H->running_stmt, 0); |
| 111 | + } |
| 112 | +} |
| 113 | + |
| 114 | +static zend_always_inline void pgsql_discard_running_stmt(pdo_pgsql_db_handle *H) |
| 115 | +{ |
| 116 | + if (H->running_stmt) { |
| 117 | + pgsql_stmt_finish(H->running_stmt, FIN_DISCARD); |
| 118 | + } |
| 119 | + |
| 120 | + PGresult *pgsql_result; |
| 121 | + bool first = true; |
| 122 | + while ((pgsql_result = PQgetResult(H->server))) { |
| 123 | + /* We should not arrive here, where libpq has a result to deliver without us |
| 124 | + * having registered a running statement: |
| 125 | + * every result discarding should go through the unified pgsql_stmt_finish, |
| 126 | + * but maybe there still is an internal query that we omitted to adapt. |
| 127 | + * So instead of asserting let's just emit an informational notice, |
| 128 | + * and consume anyway (results consumption is handle-wise, so we have no formal |
| 129 | + * need for the statement). */ |
| 130 | + if (first) { |
| 131 | + php_error_docref("ref.pgsql", E_NOTICE, "Internal error: unable to link a libpq result to consume, to its origin statement"); |
| 132 | + first = false; |
| 133 | + } |
| 134 | + PQclear(pgsql_result); |
| 135 | + } |
| 136 | +} |
| 137 | + |
106 | 138 | static void _pdo_pgsql_notice(void *context, const char *message) /* {{{ */
|
107 | 139 | {
|
108 | 140 | pdo_dbh_t * dbh = (pdo_dbh_t *)context;
|
@@ -348,6 +380,7 @@ static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const zend_string *sql)
|
348 | 380 |
|
349 | 381 | bool in_trans = pgsql_handle_in_transaction(dbh);
|
350 | 382 |
|
| 383 | + pgsql_finish_running_stmt(H); |
351 | 384 | if (!(res = PQexec(H->server, ZSTR_VAL(sql)))) {
|
352 | 385 | /* fatal error */
|
353 | 386 | pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL);
|
@@ -415,6 +448,7 @@ static zend_string *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const zend_string *
|
415 | 448 | PGresult *res;
|
416 | 449 | ExecStatusType status;
|
417 | 450 |
|
| 451 | + pgsql_finish_running_stmt(H); |
418 | 452 | if (name == NULL) {
|
419 | 453 | res = PQexec(H->server, "SELECT LASTVAL()");
|
420 | 454 | } else {
|
@@ -578,6 +612,7 @@ static bool pdo_pgsql_transaction_cmd(const char *cmd, pdo_dbh_t *dbh)
|
578 | 612 | PGresult *res;
|
579 | 613 | bool ret = true;
|
580 | 614 |
|
| 615 | + pgsql_finish_running_stmt(H); |
581 | 616 | res = PQexec(H->server, cmd);
|
582 | 617 |
|
583 | 618 | if (PQresultStatus(res) != PGRES_COMMAND_OK) {
|
@@ -683,9 +718,8 @@ void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS)
|
683 | 718 | /* Obtain db Handle */
|
684 | 719 | H = (pdo_pgsql_db_handle *)dbh->driver_data;
|
685 | 720 |
|
686 |
| - while ((pgsql_result = PQgetResult(H->server))) { |
687 |
| - PQclear(pgsql_result); |
688 |
| - } |
| 721 | + pgsql_discard_running_stmt(H); |
| 722 | + |
689 | 723 | pgsql_result = PQexec(H->server, query);
|
690 | 724 |
|
691 | 725 | efree(query);
|
@@ -807,9 +841,8 @@ void pgsqlCopyFromFile_internal(INTERNAL_FUNCTION_PARAMETERS)
|
807 | 841 |
|
808 | 842 | H = (pdo_pgsql_db_handle *)dbh->driver_data;
|
809 | 843 |
|
810 |
| - while ((pgsql_result = PQgetResult(H->server))) { |
811 |
| - PQclear(pgsql_result); |
812 |
| - } |
| 844 | + pgsql_discard_running_stmt(H); |
| 845 | + |
813 | 846 | pgsql_result = PQexec(H->server, query);
|
814 | 847 |
|
815 | 848 | efree(query);
|
@@ -903,9 +936,7 @@ void pgsqlCopyToFile_internal(INTERNAL_FUNCTION_PARAMETERS)
|
903 | 936 | RETURN_FALSE;
|
904 | 937 | }
|
905 | 938 |
|
906 |
| - while ((pgsql_result = PQgetResult(H->server))) { |
907 |
| - PQclear(pgsql_result); |
908 |
| - } |
| 939 | + pgsql_discard_running_stmt(H); |
909 | 940 |
|
910 | 941 | /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */
|
911 | 942 | if (pg_fields) {
|
@@ -994,9 +1025,7 @@ void pgsqlCopyToArray_internal(INTERNAL_FUNCTION_PARAMETERS)
|
994 | 1025 |
|
995 | 1026 | H = (pdo_pgsql_db_handle *)dbh->driver_data;
|
996 | 1027 |
|
997 |
| - while ((pgsql_result = PQgetResult(H->server))) { |
998 |
| - PQclear(pgsql_result); |
999 |
| - } |
| 1028 | + pgsql_discard_running_stmt(H); |
1000 | 1029 |
|
1001 | 1030 | /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */
|
1002 | 1031 | if (pg_fields) {
|
|
0 commit comments