Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
database system
Priority:
Critical
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
17 Mar 2021 at 20:56 UTC
Updated:
13 Apr 2021 at 15:19 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
joseph.olstadhere's the commit from the D9 issue
https://git.drupalcode.org/project/drupal/-/commit/11a7dd988743ad62f6ffa...
Comment #3
mcdruid commentedFirst pass at fixing this.
Some of the D9 changes can be backported, but not all. For example D9 overrides the
\Drupal\Core\Database\Driver\mysql\Connection::doCommit()method in the MySQL driver whereas D7 has no such method and deliberately avoids directly callingcommit()on the PDO connection.This patch (I will try to start using MRs instead soon!) avoids the "exception when the first transaction is committed following a DDL statement" mentioned in the IS by simply bailing out of commits (triggered from the transaction's destructor) if there is no active transaction (IIUC PHP versions before PHP 8 didn't detect this condition in the same way).
That means
\DatabaseTransactionTestCase::testTransactionWithDdlStatement()will now run through, but there are still a couple of problems that need to be fixed.D9 changed the behaviour of rollbacks in a way I'm struggling to reproduce in D7, not least because I've yet to figure out how to get the test to properly catch the new warning which is triggered. IIUC this only happens in PHP 8 so it should be okay to use e.g.
Throwable.I think the functionality change is likely okay and it's just the test we need to fix.
There's also one other assertion failing in the test which I've put a comment next to, but I've not dug into what's happening there yet.
Comment #4
mcdruid commentedBlocked on #3200708: [PHP8] Error: User-supplied statement does not accept constructor arguments in PDO->prepare() (and maybe others?) to get tests running through properly for PHP 8
Comment #5
mcdruid commentedI think setting a custom error handler like this works to catch the new E_USER_WARNING which is emitted when a rollback's attempted with no transaction active.
However, this rollback (of transaction3) is throwing that exception too:
...and that last assertion is failing.
So we get something like this (where the last test pass shows the new error handler working for the rollback within the try/catch, IIUC):
I'm not sure what's going on here yet - it looks like almost exactly the same test code is still in D9, which suggests to me that the rollback should be successful but is not.
Perhaps I've broken the rollback method in my attempt to backport the D9 changes? Will try to dive into what's going on.
Sadly I don't think we're getting the results for this test from drupalci yet because of other PHP 8 problems.
Comment #6
mcdruid commentedI had managed to break rollbacks... and to misname the previous patch as 6 when it should have been 5. Oops.
This new patch #6 adds a simple
\DatabaseConnection_mysql::doCommit()method which checks whether PDO reports that a transaction is in flight before trying to commit.This avoids the new PHP 8 behaviour where "PDOException: There is no active transaction" is thrown, in pretty much the same way that D9 does so.
I believe this backport now fixes both commits and rollbacks. DatabaseTransactionTestCase now passes for me in PHP 8:
We'd want a Change Record to explain the new E_USER_WARNING which is thrown in PHP 8 when a rollback is attempted when there's no transaction active.
Comment #7
fabianx commentedApproved, looks great to me and better to keep BC compatibility for PHP8 and continue to fail silently.
Comment #15
mcdruid commentedTweaked the comment to say "Before PHP 8" rather than "On PHP 7" which is more appropriate for D7, as discussed with @Fabianx.
Added a CR.
Thanks everyone!
Comment #16
joseph.olstadThanks!