From 9580fcfeddf85f6510217fec2f596f6f5169f251 Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Fri, 31 Oct 2014 18:10:01 +0100 Subject: [PATCH] Fixed bug #67462 PDO_PGSQL::beginTransaction() wrongly throws exception when not in transaction --- NEWS | 4 ++++ ext/pdo_pgsql/pgsql_driver.c | 28 ++++++++++++++++--------- ext/pdo_pgsql/tests/bug67462.phpt | 34 +++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 ext/pdo_pgsql/tests/bug67462.phpt diff --git a/NEWS b/NEWS index 9e5e1388c8..ec68e1d730 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,10 @@ PHP NEWS . Fixed bug #68087 (ODBC not correctly reading DATE column when preceded by a VARCHAR column) (Keyur Govande) +- PDO_pgsql: + . Fixed bug #67462 (PDO_PGSQL::beginTransaction() wrongly throws exception + when not in transaction) (Matteo) + - SPL: . Fixed bug #68128 (Regression in RecursiveRegexIterator) (Tjerk) diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 3be9359216..9638c72fe6 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -465,6 +465,15 @@ static int pdo_pgsql_check_liveness(pdo_dbh_t *dbh TSRMLS_DC) } /* }}} */ +static int pgsql_handle_in_transaction(pdo_dbh_t *dbh TSRMLS_DC) +{ + pdo_pgsql_db_handle *H; + + H = (pdo_pgsql_db_handle *)dbh->driver_data; + + return PQtransactionStatus(H->server) > PQTRANS_IDLE; +} + static int pdo_pgsql_transaction_cmd(const char *cmd, pdo_dbh_t *dbh TSRMLS_DC) { pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; @@ -489,7 +498,15 @@ static int pgsql_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) static int pgsql_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) { - return pdo_pgsql_transaction_cmd("COMMIT", dbh TSRMLS_CC); + int ret = pdo_pgsql_transaction_cmd("COMMIT", dbh TSRMLS_CC); + + /* When deferred constraints are used the commit could + fail, and a ROLLBACK implicitly ran. See bug #67462 */ + if (!ret) { + dbh->in_txn = pgsql_handle_in_transaction(dbh); + } + + return ret; } static int pgsql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) @@ -497,15 +514,6 @@ static int pgsql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) return pdo_pgsql_transaction_cmd("ROLLBACK", dbh TSRMLS_CC); } -static int pgsql_handle_in_transaction(pdo_dbh_t *dbh TSRMLS_DC) -{ - pdo_pgsql_db_handle *H; - - H = (pdo_pgsql_db_handle *)dbh->driver_data; - - return PQtransactionStatus(H->server); -} - /* {{{ proto string PDO::pgsqlCopyFromArray(string $table_name , array $rows [, string $delimiter [, string $null_as ] [, string $fields]) Returns true if the copy worked fine or false if error */ static PHP_METHOD(PDO, pgsqlCopyFromArray) diff --git a/ext/pdo_pgsql/tests/bug67462.phpt b/ext/pdo_pgsql/tests/bug67462.phpt new file mode 100644 index 0000000000..888b19c248 --- /dev/null +++ b/ext/pdo_pgsql/tests/bug67462.phpt @@ -0,0 +1,34 @@ +--TEST-- +PDO PgSQL Bug #67462 (PDO_PGSQL::beginTransaction() wrongly throws exception when not in transaction) +--SKIPIF-- + +--FILE-- +setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + +$pdo->beginTransaction(); + +try { + $pdo->query("CREATE TABLE b67462 (a int NOT NULL PRIMARY KEY DEFERRABLE INITIALLY DEFERRED)"); + $pdo->query("INSERT INTO b67462 VALUES (1), (1)"); + + var_dump($pdo->inTransaction()); + $pdo->commit(); // This should fail! +} catch (\Exception $e) { + var_dump($pdo->inTransaction()); + var_dump($pdo->beginTransaction()); +} + +?> +--EXPECT-- +bool(true) +bool(false) +bool(true) -- 2.40.0