RFC: mysqli::in_transaction

php.internals

Grégoire PARIS

5 years ago
Hi, Grégoire Paris here! I'm a maintainer on Doctrine projects and today, I'd like to talk to you about something we would like to propose. We have found that PDO has a method called PDO::inTransaction() that we would like to mimic in the API of doctrine/dbal, a database abstraction layer many of you may already know. We would like to implement this in driver abstraction classes, so that we can call the new method from our existing Connection::isTransactionActive() method. Connection::isTransactionActive() currently relies on a counter, but as you may know, this is not foolproof because of how some RDBMS like MySQL will implicitly commit transactions when DDL is involved. In such cases, the method will return true when it should really return false. Our problem is, we are missing an API similar to PDO::inTransaction() for the mysqli driver. We would like to contribute that API and Sergei Morozov already worked on a patch. It is available at https://github.com/php/php-src/compare/PHP-8.0...morozov:mysqli-in-transaction , and can be tested as follows: --- <?php $conn = mysqli_connect('127.0.0.1', 'root', '', 'doctrine'); if (!$conn) { exit(1); } echo 'Testing commit, procedural interface:', PHP_EOL; var_dump(mysqli_in_transaction($conn)); mysqli_begin_transaction($conn); var_dump(mysqli_in_transaction($conn)); mysqli_commit($conn); var_dump(mysqli_in_transaction($conn)); echo PHP_EOL; echo 'Testing rollback, OO interface:', PHP_EOL; var_dump($conn->in_transaction()); $conn->begin_transaction(); var_dump($conn->in_transaction()); $conn->rollback(); var_dump($conn->in_transaction()); echo PHP_EOL; echo 'Testing DDL:', PHP_EOL; mysqli_query($conn, 'DROP TABLE IF EXISTS foo'); mysqli_begin_transaction($conn); var_dump(mysqli_in_transaction($conn)); mysqli_query($conn, 'CREATE TABLE foo(id INT)'); var_dump(mysqli_in_transaction($conn)); echo PHP_EOL; ---
> Testing commit, procedural interface: > bool(false) > bool(true) > bool(false) > > Testing rollback, OO interface: > bool(false) > bool(true) > bool(false) > > Testing DDL: > bool(true) > bool(false)
Would it be OK for us to go ahead and contribute this? The DBAL RFC can be found at https://github.com/doctrine/dbal/issues/4616 Best regards,
-- Grégoire Paris

Gabriel Ostrolucky

5 years ago
What about OCI8 driver? That’s also included in core. Also a sidermark: SQLSrv and IBMDB2 are not part of core, but situation should be checked in those as well, since they are supported in DBA tooL Powered by Mailbutler <https://www.mailbutler.io/?utm_source=watermark&utm_medium=email&utm_campaign=watermark-essential-email>, the email extension that does it all

Sergei Morozov

5 years ago
Hi, There is the SQLGetConnectAttr method and the SQL_ATTR_AUTOCOMMIT attribute (part of the ISO 92 standard) which should allow detecting the transaction state at the driver level. This API used by the SQL Server extensions (to manage the transaction) and it also seems to be available for Oracle and IBM DB2 drivers as well. I'd like to start with the mysqli driver specifically because: 1. MySQL is one of the DB platforms that doesn't support in transactions. 2. It's much more widely used with PHP than Oracle. We can attempt to implement this functionality in different DB extensions independently since they don't depend on each other. On Mon, Apr 26, 2021 at 1:11 AM Gabriel O <gadelat@gmail.com> wrote:
> What about OCI8 driver? That’s also included in core. > > Also a sidermark: SQLSrv and IBMDB2 are not part of core, but situation > should be checked in those as well, since they are supported in DBA tooL > > Powered by *Mailbutler > <https://www.mailbutler.io/?utm_source=watermark&utm_medium=email&utm_campaign=watermark-essential-email>*, > the email extension that does it all >
-- Sergei Morozov