iliaa                                    Mon, 26 Oct 2009 02:02:28 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=289924

Log:
- Fixed bug #49985 (pdo_pgsql prepare() re-use previous aborted transaction).

Bug: http://bugs.php.net/49985 (Open) pdo_pgsql prepare() re-use previous 
aborted transaction
      
Changed paths:
    U   php/php-src/branches/PHP_5_2/NEWS
    U   php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pgsql_statement.c
    U   php/php-src/branches/PHP_5_3/NEWS
    U   php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pgsql_statement.c
    U   php/php-src/trunk/ext/pdo_pgsql/pgsql_statement.c

Modified: php/php-src/branches/PHP_5_2/NEWS
===================================================================
--- php/php-src/branches/PHP_5_2/NEWS	2009-10-25 20:47:27 UTC (rev 289923)
+++ php/php-src/branches/PHP_5_2/NEWS	2009-10-26 02:02:28 UTC (rev 289924)
@@ -14,6 +14,8 @@

 - Fixed bug #49990 (SNMP3 warning message about security level printed twice).
   (Jani)
+- Fixed bug #49985 (pdo_pgsql prepare() re-use previous aborted
+  transaction). (ben dot pineau at gmail dot com, Ilia)
 - Fixed bug #49972 (AppendIterator undefined function crash). (Johannes)
 - Fixed bug #49855 (import_request_variables() always returns NULL). (Ilia,
   sjoerd at php dot net)

Modified: php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pgsql_statement.c
===================================================================
--- php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pgsql_statement.c	2009-10-25 20:47:27 UTC (rev 289923)
+++ php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pgsql_statement.c	2009-10-26 02:02:28 UTC (rev 289924)
@@ -134,6 +134,14 @@
 		/* using a prepared statement */

 		if (!S->is_prepared) {
+			/* don't break the whole current transaction when the first
+			 * prepare tentative fails (happens when the prepared statement
+			 * already exists). ignore those SAVEPOINT queries results because
+			 * we don't care (may be outside transaction?).
+			 */
+			char buf[100]; /* stmt_name == "pdo_pgsql_cursor_%08x" */
+			snprintf(buf, sizeof(buf), "SAVEPOINT %s", S->stmt_name);
+			PQexec(H->server, buf);
 stmt_retry:
 			/* we deferred the prepare until now, because we didn't
 			 * know anything about the parameter types; now we do */
@@ -153,12 +161,14 @@
 					/* 42P05 means that the prepared statement already existed. this can happen if you use
 					 * a connection pooling software line pgpool which doesn't close the db-connection once
 					 * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no
-					 * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we
-					 * deallocate it and retry ONCE (thies 2005.12.15)
+					 * chance to DEALLOCATE the prepared statements it has created. Also happens if we tried
+					 * to DEALLOCATE the same statement name in an aborted transaction. so, if we hit a 42P05
+					 * we deallocate it and retry ONCE (thies 2005.12.15)
 					 */
 					if (!strcmp(sqlstate, "42P05")) {
-						char buf[100]; /* stmt_name == "pdo_pgsql_cursor_%08x" */
 						PGresult *res;
+						snprintf(buf, sizeof(buf), "ROLLBACK TO SAVEPOINT %s", S->stmt_name);
+						PQexec(H->server, buf);
 						snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name);
 						res = PQexec(H->server, buf);
 						if (res) {
@@ -166,11 +176,15 @@
 						}
 						goto stmt_retry;
 					} else {
+						snprintf(buf, sizeof(buf), "RELEASE SAVEPOINT %s", S->stmt_name);
+						PQexec(H->server, buf);
 						pdo_pgsql_error_stmt(stmt, status, sqlstate);
 						return 0;
 					}
 				}
 			}
+			snprintf(buf, sizeof(buf), "RELEASE SAVEPOINT %s", S->stmt_name);
+			PQexec(H->server, buf);
 		}
 		S->result = PQexecPrepared(H->server, S->stmt_name,
 				stmt->bound_params ?

Modified: php/php-src/branches/PHP_5_3/NEWS
===================================================================
--- php/php-src/branches/PHP_5_3/NEWS	2009-10-25 20:47:27 UTC (rev 289923)
+++ php/php-src/branches/PHP_5_3/NEWS	2009-10-26 02:02:28 UTC (rev 289924)
@@ -13,6 +13,8 @@

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

Modified: php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pgsql_statement.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pgsql_statement.c	2009-10-25 20:47:27 UTC (rev 289923)
+++ php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pgsql_statement.c	2009-10-26 02:02:28 UTC (rev 289924)
@@ -162,6 +162,14 @@
 		/* using a prepared statement */

 		if (!S->is_prepared) {
+			/* don't break the whole current transaction when the first
+			 * prepare tentative fails (happens when the prepared statement
+			 * already exists). ignore those SAVEPOINT queries results because
+			 * we don't care (may be outside transaction?).
+			 */
+			char buf[100]; /* stmt_name == "pdo_pgsql_cursor_%08x" */
+			snprintf(buf, sizeof(buf), "SAVEPOINT %s", S->stmt_name);
+			PQexec(H->server, buf);
 stmt_retry:
 			/* we deferred the prepare until now, because we didn't
 			 * know anything about the parameter types; now we do */
@@ -181,12 +189,14 @@
 					/* 42P05 means that the prepared statement already existed. this can happen if you use
 					 * a connection pooling software line pgpool which doesn't close the db-connection once
 					 * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no
-					 * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we
-					 * deallocate it and retry ONCE (thies 2005.12.15)
+					 * chance to DEALLOCATE the prepared statements it has created. Also happens if we tried
+					 * to DEALLOCATE the same statement name in an aborted transaction. so, if we hit a 42P05
+					 * we deallocate it and retry ONCE (thies 2005.12.15)
 					 */
 					if (!strcmp(sqlstate, "42P05")) {
-						char buf[100]; /* stmt_name == "pdo_crsr_%016lx" */
 						PGresult *res;
+						snprintf(buf, sizeof(buf), "ROLLBACK TO SAVEPOINT %s", S->stmt_name);
+						PQexec(H->server, buf);
 						snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name);
 						res = PQexec(H->server, buf);
 						if (res) {
@@ -194,11 +204,15 @@
 						}
 						goto stmt_retry;
 					} else {
+						snprintf(buf, sizeof(buf), "RELEASE SAVEPOINT %s", S->stmt_name);
+						PQexec(H->server, buf);
 						pdo_pgsql_error_stmt(stmt, status, sqlstate);
 						return 0;
 					}
 				}
 			}
+			snprintf(buf, sizeof(buf), "RELEASE SAVEPOINT %s", S->stmt_name);
+			PQexec(H->server, buf);
 		}
 		S->result = PQexecPrepared(H->server, S->stmt_name,
 				stmt->bound_params ?

Modified: php/php-src/trunk/ext/pdo_pgsql/pgsql_statement.c
===================================================================
--- php/php-src/trunk/ext/pdo_pgsql/pgsql_statement.c	2009-10-25 20:47:27 UTC (rev 289923)
+++ php/php-src/trunk/ext/pdo_pgsql/pgsql_statement.c	2009-10-26 02:02:28 UTC (rev 289924)
@@ -162,6 +162,14 @@
 		/* using a prepared statement */

 		if (!S->is_prepared) {
+			/* don't break the whole current transaction when the first
+			 * prepare tentative fails (happens when the prepared statement
+			 * already exists). ignore those SAVEPOINT queries results because
+			 * we don't care (may be outside transaction?).
+			 */
+			char buf[100]; /* stmt_name == "pdo_pgsql_cursor_%08x" */
+			snprintf(buf, sizeof(buf), "SAVEPOINT %s", S->stmt_name);
+			PQexec(H->server, buf);
 stmt_retry:
 			/* we deferred the prepare until now, because we didn't
 			 * know anything about the parameter types; now we do */
@@ -181,12 +189,14 @@
 					/* 42P05 means that the prepared statement already existed. this can happen if you use
 					 * a connection pooling software line pgpool which doesn't close the db-connection once
 					 * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no
-					 * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we
-					 * deallocate it and retry ONCE (thies 2005.12.15)
+					 * chance to DEALLOCATE the prepared statements it has created. Also happens if we tried
+					 * to DEALLOCATE the same statement name in an aborted transaction. so, if we hit a 42P05
+					 * we deallocate it and retry ONCE (thies 2005.12.15)
 					 */
 					if (!strcmp(sqlstate, "42P05")) {
-						char buf[100]; /* stmt_name == "pdo_crsr_%016lx" */
 						PGresult *res;
+						snprintf(buf, sizeof(buf), "ROLLBACK TO SAVEPOINT %s", S->stmt_name);
+						PQexec(H->server, buf);
 						snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name);
 						res = PQexec(H->server, buf);
 						if (res) {
@@ -194,11 +204,15 @@
 						}
 						goto stmt_retry;
 					} else {
+						snprintf(buf, sizeof(buf), "RELEASE SAVEPOINT %s", S->stmt_name);
+						PQexec(H->server, buf);
 						pdo_pgsql_error_stmt(stmt, status, sqlstate);
 						return 0;
 					}
 				}
 			}
+			snprintf(buf, sizeof(buf), "RELEASE SAVEPOINT %s", S->stmt_name);
+			PQexec(H->server, buf);
 		}
 		S->result = PQexecPrepared(H->server, S->stmt_name,
 				stmt->bound_params ?
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to