From 2a481b01fb1af7ee30f7a6e4c36defee94fbcaf8 Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Wed, 4 Nov 2009 19:32:27 +0000 Subject: [PATCH] - Properly fixed bug #49985 (pdo_pgsql prepare() re-use previous aborted transaction). # Removed usage of the memory address when generating prepared statemend names # as uniqueness can't be enforced. Used a statment counter instead. --- NEWS | 2 +- ext/pdo_pgsql/pgsql_driver.c | 4 ++-- ext/pdo_pgsql/pgsql_statement.c | 2 +- ext/pdo_pgsql/php_pdo_pgsql_int.h | 1 + ext/pdo_pgsql/tests/bug_49985.phpt | 35 ++++++++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 ext/pdo_pgsql/tests/bug_49985.phpt diff --git a/NEWS b/NEWS index 6a034b1933..427f4603c7 100644 --- a/NEWS +++ b/NEWS @@ -24,7 +24,7 @@ PHP NEWS - 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) + transaction). (ben dot pineau at gmail dot com, Ilia, Matteo) - Fixed bug #49921 (Curl post upload functions changed). (Ilia) - Fixed bug #49972 (AppendIterator undefined function crash). (Johannes) - Fixed bug #49855 (import_request_variables() always returns NULL). (Ilia, diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 28d59a19fb..97e58006d2 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -233,7 +233,7 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, efree(S->cursor_name); } /* TODO: check how scrollable cursors related to prepared statements */ - spprintf(&S->cursor_name, 0, "pdo_pgsql_cursor_%08x", (unsigned int) stmt); + spprintf(&S->cursor_name, 0, "pdo_crsr_%08x", ++H->stmt_counter); } #if HAVE_PQPREPARE @@ -261,7 +261,7 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, return 0; } - spprintf(&S->stmt_name, 0, "pdo_pgsql_stmt_%08x", (unsigned int)stmt); + spprintf(&S->stmt_name, 0, "pdo_stmt_%08x", ++H->stmt_counter); /* that's all for now; we'll defer the actual prepare until the first execute call */ if (nsql) { diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index ce53d84922..fbfdde1c07 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -157,7 +157,7 @@ stmt_retry: * deallocate it and retry ONCE (thies 2005.12.15) */ if (!strcmp(sqlstate, "42P05")) { - char buf[100]; /* stmt_name == "pdo_pgsql_cursor_%08x" */ + char buf[100]; /* stmt_name == "pdo_crsr_%08x" */ PGresult *res; snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name); res = PQexec(H->server, buf); diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h index d54d4e7afe..d1f658d719 100644 --- a/ext/pdo_pgsql/php_pdo_pgsql_int.h +++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h @@ -50,6 +50,7 @@ typedef struct { int emulate_prepares; int disable_native_prepares; #endif + unsigned int stmt_counter; } pdo_pgsql_db_handle; typedef struct { diff --git a/ext/pdo_pgsql/tests/bug_49985.phpt b/ext/pdo_pgsql/tests/bug_49985.phpt new file mode 100644 index 0000000000..7ada87630a --- /dev/null +++ b/ext/pdo_pgsql/tests/bug_49985.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #49985 (pdo_pgsql prepare() re-use previous aborted transaction) +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$db->exec("CREATE TABLE test (a int PRIMARY KEY)"); + +for ($i = 0; $i < 3; $i++) { + try { + $db->beginTransaction(); + $stmt = $db->prepare("INSERT INTO test (a) VALUES (?)"); + var_dump($stmt->execute(array(1))); + $db->commit(); + } catch (Exception $e) { + echo $e->getMessage()."\n"; + $db->rollback(); + } +} + +?> +--EXPECTF-- +bool(true) +SQLSTATE[23505]: %s"test_pkey" +SQLSTATE[23505]: %s"test_pkey" + -- 2.40.0