]> granicus.if.org Git - php/commitdiff
- Properly fixed bug #49985 (pdo_pgsql prepare() re-use previous aborted transaction).
authorMatteo Beccati <mbeccati@php.net>
Wed, 4 Nov 2009 19:32:27 +0000 (19:32 +0000)
committerMatteo Beccati <mbeccati@php.net>
Wed, 4 Nov 2009 19:32:27 +0000 (19:32 +0000)
# Removed usage of the memory address when generating prepared statemend names
# as uniqueness can't be enforced. Used a statment counter instead.

ext/pdo_pgsql/pgsql_driver.c
ext/pdo_pgsql/pgsql_statement.c
ext/pdo_pgsql/php_pdo_pgsql_int.h
ext/pdo_pgsql/tests/bug_49985.phpt [new file with mode: 0644]

index cd13fc36efbdd90fd3d199bb4441b2825ae4f3cc..c844abbc3243bcd48694303228a4dfabb61a6830 100644 (file)
@@ -232,7 +232,7 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
                if (S->cursor_name) {
                        efree(S->cursor_name);
                }
-               spprintf(&S->cursor_name, 0, "pdo_crsr_%016lx", (unsigned long) stmt);
+               spprintf(&S->cursor_name, 0, "pdo_crsr_%08x", ++H->stmt_counter);
 #if HAVE_PQPREPARE
                emulate = 1;
 #endif
@@ -262,7 +262,7 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
                        return 0;
                }
 
-               spprintf(&S->stmt_name, 0, "pdo_stmt_%016lx", (unsigned long)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) {
index f19a6646c6bd0c4471c4e0c750859fc487f7dd0f..c465c3f7d5585883950b9805fbf0876df5979c5d 100644 (file)
@@ -185,7 +185,7 @@ stmt_retry:
                                         * deallocate it and retry ONCE (thies 2005.12.15)
                                         */
                                        if (!strcmp(sqlstate, "42P05")) {
-                                               char buf[100]; /* stmt_name == "pdo_crsr_%016lx" */
+                                               char buf[100]; /* stmt_name == "pdo_crsr_%08x" */
                                                PGresult *res;
                                                snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name);
                                                res = PQexec(H->server, buf);
index 4471a80ac41dd37c0c24338d256cbbbe48cc5e1c..2d6b812cad3121ffa2255366f3883c3477941063 100644 (file)
@@ -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 (file)
index 0000000..7ada876
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+Bug #49985 (pdo_pgsql prepare() re-use previous aborted transaction)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->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"
+