|
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;
|
@@ -349,6 +381,7 @@ static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const zend_string *sql)
|
349 | 381 |
|
350 | 382 | bool in_trans = pgsql_handle_in_transaction(dbh);
|
351 | 383 |
|
| 384 | + pgsql_finish_running_stmt(H); |
352 | 385 | if (!(res = PQexec(H->server, ZSTR_VAL(sql)))) {
|
353 | 386 | /* fatal error */
|
354 | 387 | pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL);
|
@@ -416,6 +449,7 @@ static zend_string *pdo_pgsql_last_insert_id(pdo_dbh_t *dbh, const zend_string *
|
416 | 449 | PGresult *res;
|
417 | 450 | ExecStatusType status;
|
418 | 451 |
|
| 452 | + pgsql_finish_running_stmt(H); |
419 | 453 | if (name == NULL) {
|
420 | 454 | res = PQexec(H->server, "SELECT LASTVAL()");
|
421 | 455 | } else {
|
@@ -579,6 +613,7 @@ static bool pdo_pgsql_transaction_cmd(const char *cmd, pdo_dbh_t *dbh)
|
579 | 613 | PGresult *res;
|
580 | 614 | bool ret = true;
|
581 | 615 |
|
| 616 | + pgsql_finish_running_stmt(H); |
582 | 617 | res = PQexec(H->server, cmd);
|
583 | 618 |
|
584 | 619 | if (PQresultStatus(res) != PGRES_COMMAND_OK) {
|
@@ -684,9 +719,8 @@ void pgsqlCopyFromArray_internal(INTERNAL_FUNCTION_PARAMETERS)
|
684 | 719 | /* Obtain db Handle */
|
685 | 720 | H = (pdo_pgsql_db_handle *)dbh->driver_data;
|
686 | 721 |
|
687 |
| - while ((pgsql_result = PQgetResult(H->server))) { |
688 |
| - PQclear(pgsql_result); |
689 |
| - } |
| 722 | + pgsql_discard_running_stmt(H); |
| 723 | + |
690 | 724 | pgsql_result = PQexec(H->server, query);
|
691 | 725 |
|
692 | 726 | efree(query);
|
@@ -808,9 +842,8 @@ void pgsqlCopyFromFile_internal(INTERNAL_FUNCTION_PARAMETERS)
|
808 | 842 |
|
809 | 843 | H = (pdo_pgsql_db_handle *)dbh->driver_data;
|
810 | 844 |
|
811 |
| - while ((pgsql_result = PQgetResult(H->server))) { |
812 |
| - PQclear(pgsql_result); |
813 |
| - } |
| 845 | + pgsql_discard_running_stmt(H); |
| 846 | + |
814 | 847 | pgsql_result = PQexec(H->server, query);
|
815 | 848 |
|
816 | 849 | efree(query);
|
@@ -904,9 +937,7 @@ void pgsqlCopyToFile_internal(INTERNAL_FUNCTION_PARAMETERS)
|
904 | 937 | RETURN_FALSE;
|
905 | 938 | }
|
906 | 939 |
|
907 |
| - while ((pgsql_result = PQgetResult(H->server))) { |
908 |
| - PQclear(pgsql_result); |
909 |
| - } |
| 940 | + pgsql_discard_running_stmt(H); |
910 | 941 |
|
911 | 942 | /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */
|
912 | 943 | if (pg_fields) {
|
@@ -995,9 +1026,7 @@ void pgsqlCopyToArray_internal(INTERNAL_FUNCTION_PARAMETERS)
|
995 | 1026 |
|
996 | 1027 | H = (pdo_pgsql_db_handle *)dbh->driver_data;
|
997 | 1028 |
|
998 |
| - while ((pgsql_result = PQgetResult(H->server))) { |
999 |
| - PQclear(pgsql_result); |
1000 |
| - } |
| 1029 | + pgsql_discard_running_stmt(H); |
1001 | 1030 |
|
1002 | 1031 | /* using pre-9.0 syntax as PDO_pgsql is 7.4+ compatible */
|
1003 | 1032 | if (pg_fields) {
|
|
0 commit comments