diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index eb77693f5bf..8917b9b0dc1 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -814,9 +814,7 @@ static zend_result pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *v } fail: - if (attr == PDO_ATTR_AUTOCOMMIT) { - zend_throw_exception_ex(php_pdo_get_exception(), 0, "The auto-commit mode cannot be changed for this driver"); - } else if (!dbh->methods->set_attribute) { + if (!dbh->methods->set_attribute) { pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support setting attributes"); } else { PDO_HANDLE_DBH_ERR(); diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index a666489a503..641a9add1ae 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -349,7 +349,11 @@ static int mysql_handle_commit(pdo_dbh_t *dbh) { PDO_DBG_ENTER("mysql_handle_commit"); PDO_DBG_INF_FMT("dbh=%p", dbh); - PDO_DBG_RETURN(0 == mysql_commit(((pdo_mysql_db_handle *)dbh->driver_data)->server)); + if (mysql_commit(((pdo_mysql_db_handle *)dbh->driver_data)->server)) { + pdo_mysql_error(dbh); + PDO_DBG_RETURN(0); + } + PDO_DBG_RETURN(1); } /* }}} */ @@ -358,7 +362,11 @@ static int mysql_handle_rollback(pdo_dbh_t *dbh) { PDO_DBG_ENTER("mysql_handle_rollback"); PDO_DBG_INF_FMT("dbh=%p", dbh); - PDO_DBG_RETURN(0 == mysql_rollback(((pdo_mysql_db_handle *)dbh->driver_data)->server)); + if (mysql_rollback(((pdo_mysql_db_handle *)dbh->driver_data)->server)) { + pdo_mysql_error(dbh); + PDO_DBG_RETURN(0); + } + PDO_DBG_RETURN(1); } /* }}} */ @@ -368,7 +376,11 @@ static inline int mysql_handle_autocommit(pdo_dbh_t *dbh) PDO_DBG_ENTER("mysql_handle_autocommit"); PDO_DBG_INF_FMT("dbh=%p", dbh); PDO_DBG_INF_FMT("dbh->autocommit=%d", dbh->auto_commit); - PDO_DBG_RETURN(0 == mysql_autocommit(((pdo_mysql_db_handle *)dbh->driver_data)->server, dbh->auto_commit)); + if (mysql_autocommit(((pdo_mysql_db_handle *)dbh->driver_data)->server, dbh->auto_commit)) { + pdo_mysql_error(dbh); + PDO_DBG_RETURN(0); + } + PDO_DBG_RETURN(1); } /* }}} */ @@ -385,7 +397,9 @@ static int pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) /* ignore if the new value equals the old one */ if (dbh->auto_commit ^ bval) { dbh->auto_commit = bval; - mysql_handle_autocommit(dbh); + if (!mysql_handle_autocommit(dbh)) { + PDO_DBG_RETURN(0); + } } PDO_DBG_RETURN(1); diff --git a/ext/pdo_mysql/tests/bug66528.phpt b/ext/pdo_mysql/tests/bug66528.phpt new file mode 100644 index 00000000000..a5c79c12b32 --- /dev/null +++ b/ext/pdo_mysql/tests/bug66528.phpt @@ -0,0 +1,51 @@ +--TEST-- +Bug #66528: No PDOException or errorCode if database becomes unavailable before PDO::commit +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + +$dbh->exec('DROP TABLE IF EXISTS test'); +$dbh->exec('CREATE TABLE test (a int) engine=innodb'); +$dbh->beginTransaction(); +$dbh->exec('INSERT INTO test (a) VALUES (1), (2)'); +$stmt = $dbh->query('SELECT * FROM test'); + +try { + $dbh->commit(); +} catch (PDOException $e) { + echo $e->getMessage(), "\n"; +} + +try { + $dbh->rollBack(); +} catch (PDOException $e) { + echo $e->getMessage(), "\n"; +} + +try { + $dbh->setAttribute(PDO::ATTR_AUTOCOMMIT, false); +} catch (PDOException $e) { + echo $e->getMessage(), "\n"; +} + +?> +--CLEAN-- + +--EXPECT-- +SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. +SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. +SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.