-
Notifications
You must be signed in to change notification settings - Fork 820
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ENHANCEMENT Ensure test DB is flushed on either DDL or transaction-disabled tests #8193
ENHANCEMENT Ensure test DB is flushed on either DDL or transaction-disabled tests #8193
Conversation
Note: We'll need to PR to other modules |
ok, there's still a bug. SapphireTest::setUpBeforeClass() has this code. // Build DB if we have objects
if (static::getExtraDataObjects()) {
DataObject::reset();
static::resetDBSchema(true, true);
} We need to occasionally do this on setUp() (not always setupBeforeClass) so it needs refactoring. |
Yay fixed it. |
Postgres is failing for some reason :/ |
Yeah that's ok. I'll test postgres locally. |
Error is in security somewhere. |
src/ORM/Connect/TempDatabase.php
Outdated
@@ -232,7 +245,12 @@ public function resetDBSchema(array $extraDataObjects = []) | |||
// pgsql doesn't allow schema updates inside transactions | |||
// so we need to rollback any transactions before commencing a schema reset | |||
if ($this->hasStarted()) { | |||
$this->rollbackTransaction(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok it turns out this code doesn't work.
Trying
public function resetDBSchema(array $extraDataObjects = [])
{
if (!$this->isUsed()) {
return;
}
try {
$this->rebuildTables($extraDataObjects);
} catch (DatabaseException $ex) {
// In case of error during build force a hard reset
// e.g. pgsql doesn't allow schema updates inside transactions
$this->kill();
$this->build();
$this->rebuildTables($extraDataObjects);
}
}
@dhensby seem ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PHP Fatal error: Uncaught SilverStripe\ORM\Connect\DatabaseException: Couldn't run query:
SELECT tablename
FROM pg_catalog.pg_tables
WHERE schemaname = $1 AND tablename NOT ILIKE 'pg\\_%' AND tablename NOT ILIKE 'sql\\_%'
ERROR: current transaction is aborted, commands ignored until end of transaction block in /Users/dmooyman/Sites/ss42test/vendor/silverstripe/framework/src/ORM/Connect/DBConnector.php:64
Stack trace:
#0 /Users/dmooyman/Sites/ss42test/vendor/silverstripe/postgresql/code/PostgreSQLConnector.php(234): SilverStripe\ORM\Connect\DBConnector->databaseError('Couldn't run qu...', 256, 'SELECT tablenam...', Array)
#1 /Users/dmooyman/Sites/ss42test/vendor/silverstripe/framework/src/ORM/Connect/Database.php(168): SilverStripe\PostgreSQL\PostgreSQLConnector->preparedQuery('SELECT tablenam...', Array, 256)
#2 /Users/dmooyman/Sites/ss42test/vendor/silverstripe/framework/src/ORM/Connect/Database.php(222): SilverStripe\ORM\Connect\Database->SilverStripe\ORM\Connect\{closure}('SELECT tablenam...')
#3 /Users/dmooyman/Sites/s in /Users/dmooyman/Sites/ss42test/vendor/silverstripe/framework/src/ORM/Connect/DBConnector.php on line 64
WHY
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need rollbackRecursive() on database.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's doing the rollback, but the rollback doesn't seem to actually rollback on postgres.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, there is like 6 levels of nesting at this error. A single rollback isn't enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok the problem is hasStarted is true sometimes when there is no transaction. After a rollback hasStarted needs to stay true, even though the transaction is rolled back. It's a badly documented var.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm dropping hasStarted() and using isUsed() instead. Between runs, there will be two states:
- The DB Is populated, assume that it's ready and safe to use.
- The DB is killed, assume that it requires a rebuild.
There is no "there but needs a reset state".
@dhensby the last commit + silverstripe/silverstripe-postgresql#86 will fix postgres, at least for the tests that WERE failing. I've dropped the started flag on test DB since it's not really a state of the test db, but the test fixtures. I've shifted this into a separate state in FixtureTestState. I've also added a new API to database; databases must now report transactional nesting level, in order to enable tests to recover from incorrectly nested transactions. This is the last hour of my last day, so I'm afraid I have to hand over to @robbieaverill + @dhensby . |
Local testing is VERY promising. Only this test broke in postgres:
|
Wow green. This story was SO hard to get working properly... sorry in advance @dhensby if the new logic is hard to follow. =( |
src/ORM/Connect/Database.php
Outdated
public function transactionDepth() | ||
{ | ||
// Placeholder error for transactional DBs that don't expose depth | ||
if ($this->supportsTransactions()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this logic be the opposite, i.e. if the DB doesn't support transactions, generate a user error.
Assume this hasn't surfaced because this method is overloaded in MySQL and Postgres
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, its an error because even though you support transactions, the depth is hard coded to 0.it's a placeholder for making this api abstract.
protected function setUp() | ||
{ | ||
parent::setUp(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the benefit of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. That was my var dump holder lol
public function hasStarted() | ||
{ | ||
return $this->hasStarted; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a semver break - perhaps we should leave it there but deprecate it? I realise it won't be doing anything any more other than always returning false, which could be misleading to people using this API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too concerned about this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It wasn't in a stable tag so I'm un-api ing it.
Do we know how or why we were getting to so many levels of transaction nesting? It seems like we really shouldn't get more than 2 or 3 levels of transactions deep during a test... |
A point worth making, but not something I think needs specifically addressing as we've likely covered 99% of usecases, but the commands that cause "implicit commits" aren't necassarily just DDL queries - https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html |
b19cd9d
to
76d3c67
Compare
I've addressed some of the feedback and made some changes I felt were appropriate |
I'm wondering if the nested transaction changes will mean we need to go and update all our DB drivers to match |
Ok we lost the 💚 😞 |
src/ORM/Connect/MySQLDatabase.php
Outdated
if ($this->transactionNesting <= 0) { | ||
$this->transactionNesting = 0; | ||
$this->query('COMMIT AND ' . ($chain ? '' : 'NO ') . 'CHAIN'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like maybe this logic should remain, could explain the test breakages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this back locally and re-tested and it fixes the new failures, pushed a fix to add this back
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
derp
@dhensby the logic on the nesting method was correct before you changed it. It's ment to error if not overridden eg sqlite. Can you revert. |
ah, will do |
I've pushed the change straight into the repo with 27b60ae |
@maxime-rainville did you use "rebase merge" on this PR? I can't find the merge commit anywhere... |
…et-on-ddl This is a cherry-picked PR from 4.2 -> 4.2.0
…et-on-ddl This is a cherry-picked PR from 4.2 -> 4.2.0
@dhensby Probably. |
Fixes #8182