Skip to content

Commit 42626ae

Browse files
committed
- Fixed bug #49985 (pdo_pgsql prepare() re-use previous aborted transaction).
1 parent 70e8b40 commit 42626ae

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ PHP NEWS
1313

1414
- Fixed bug #49990 (SNMP3 warning message about security level printed twice).
1515
(Jani)
16+
- Fixed bug #49985 (pdo_pgsql prepare() re-use previous aborted
17+
transaction). (ben dot pineau at gmail dot com, Ilia)
1618
- Fixed bug #49855 (import_request_variables() always returns NULL). (Ilia,
1719
sjoerd at php dot net)
1820
- Fixed bug #49800 (SimpleXML allow (un)serialize() calls without warning).

ext/pdo_pgsql/pgsql_statement.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,14 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
162162
/* using a prepared statement */
163163

164164
if (!S->is_prepared) {
165+
/* don't break the whole current transaction when the first
166+
* prepare tentative fails (happens when the prepared statement
167+
* already exists). ignore those SAVEPOINT queries results because
168+
* we don't care (may be outside transaction?).
169+
*/
170+
char buf[100]; /* stmt_name == "pdo_pgsql_cursor_%08x" */
171+
snprintf(buf, sizeof(buf), "SAVEPOINT %s", S->stmt_name);
172+
PQexec(H->server, buf);
165173
stmt_retry:
166174
/* we deferred the prepare until now, because we didn't
167175
* know anything about the parameter types; now we do */
@@ -181,24 +189,30 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
181189
/* 42P05 means that the prepared statement already existed. this can happen if you use
182190
* a connection pooling software line pgpool which doesn't close the db-connection once
183191
* php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no
184-
* chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we
185-
* deallocate it and retry ONCE (thies 2005.12.15)
192+
* chance to DEALLOCATE the prepared statements it has created. Also happens if we tried
193+
* to DEALLOCATE the same statement name in an aborted transaction. so, if we hit a 42P05
194+
* we deallocate it and retry ONCE (thies 2005.12.15)
186195
*/
187196
if (!strcmp(sqlstate, "42P05")) {
188-
char buf[100]; /* stmt_name == "pdo_crsr_%016lx" */
189197
PGresult *res;
198+
snprintf(buf, sizeof(buf), "ROLLBACK TO SAVEPOINT %s", S->stmt_name);
199+
PQexec(H->server, buf);
190200
snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name);
191201
res = PQexec(H->server, buf);
192202
if (res) {
193203
PQclear(res);
194204
}
195205
goto stmt_retry;
196206
} else {
207+
snprintf(buf, sizeof(buf), "RELEASE SAVEPOINT %s", S->stmt_name);
208+
PQexec(H->server, buf);
197209
pdo_pgsql_error_stmt(stmt, status, sqlstate);
198210
return 0;
199211
}
200212
}
201213
}
214+
snprintf(buf, sizeof(buf), "RELEASE SAVEPOINT %s", S->stmt_name);
215+
PQexec(H->server, buf);
202216
}
203217
S->result = PQexecPrepared(H->server, S->stmt_name,
204218
stmt->bound_params ?

0 commit comments

Comments
 (0)