|
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