findTables returns an empty array when attempting to list tables for an external DB. findTables works as expected for both PostgreSQL and MySQL external databases. The bug doesn't impact core usability.
The following code works for MySQL and PostgreSQL, but fails for SQLite:
// fetch all databases in settings.php
$databases = Database::getAllConnectionInfo();
foreach ($databases as $database => $config) {
// connect to the database.
$connection = Database::getConnection('default', $database);
// fetch all tables in the database
$tables = $connection->schema()->findTables('%');
}
For now I'm using the following work around:
// fetch all databases in settings.php
$databases = Database::getAllConnectionInfo();
foreach ($databases as $database => $config) {
// connect to the database.
$connection = Database::getConnection('default', $database);
if ($config['default']['driver'] == 'sqlite') {
// Create a table query because schema()->findTables('%') returns
// an empty array for SQLite. The problem is inherent to SQLite the driver.
$connection->query("ATTACH DATABASE '" . $config['default']['database'] . "' as " . $database . ";");
$q = "SELECT name FROM " . $database . ".sqlite_master ";
$q.= "WHERE type = 'table' AND name LIKE '%' AND name NOT LIKE 'sqlite_%'";
$tables = $connection->query($q)
->fetchAllKeyed(0, 0);
}
else {
$tables = $connection->schema()->findTables('%');
}
}
I simply copied the SQL query from the SQLite driver. Essentially, the SQLite code works, the problem is in how it is attaching the database.
I believe bug is inherent in the way in which the driver is constructed. Unfortunately, I'm not familiar enough with Drupal internals to track it further.
Drupal 7 issue is #1713332: The SQLite database driver fails to drop simpletest tables
| Comment | File | Size | Author |
|---|---|---|---|
| #21 | 2949229-21.patch | 1.7 KB | andypost |
| #21 | 2949229-21-fail.patch | 732 bytes | andypost |
| #21 | interdiff.txt | 638 bytes | andypost |
Comments
Comment #2
andypostConfirm this
Comment #3
andypostHere's a quick fix
Comment #4
andypostI'm getting empty list of tables on default local setup with sqlite
Comment #5
amateescu commentedHow about adding a
$include_main = FALSEparameter to\Drupal\Core\Database\Driver\sqlite\Connection::getAttachedDatabases(), and calling it withTRUEinfindTables()? This way anyone who callsgetAttachedDatabases()should be aware that it doesn't return the main schema by default :)Also, it's really strange that
\Drupal\KernelTests\Core\Database\SchemaTest::testFindTables()doesn't fail in HEAD..Comment #6
andypostIt does not fail because tests always have
$attached_dbsnon-empty, running this test I always get kind of that in$attached_dbs:Comment #7
amateescu commentedRight, we can't test this in a kernel or functional test because of how we instantiate the database in the a environment by using prefixes. I guess manual testing will have to do for this issue :)
What do you think about the fist part of #5?
Comment #8
andypostI find in nice workaround for specific driver to manage schemas/attached databases for sqlite (recall few issues with it in pgsql meantime)
Will work on it tonight
Comment #9
andypostUsed to add tests but that really not possible, probably it need CR
To test it manually - use quickstart install (sqlite) and
drush ev 'var_dump(\Drupal::database()->schema()->findTables("%"));'which returns nothing without patch and all tables on patched core
Comment #10
amateescu commentedI also tested it manually and it works fine!
Comment #11
alexpottSo HEAD will pass this test on SQLite?
Comment #12
andypost@alexpott yes, that's just extra case for existing coverage
Basically in tests we always have kinda test93593384 database attached ( as #6 trying to explain
Comment #13
alexpottSo I've read
carefully many times. And I'm not sure the solution here is correct. I think we should do something like
The reason I don't think the solution is correct is because if you did -
var_dump(\Drupal\Core\Database\Database::getConnection('my_prefix')->schema()->findTables("%"));this would includemainand that's not right either.Comment #15
daffie commentedTo test the patch from comment #9 with only the added test.
Comment #16
andypostTest patch does not catch the issue, any idea how to cover it?
Comment #17
daffie commentedI would like to postpone this issue on #3106531: Notify in Status Report that per-table database prefixes are no longer supported, and will throw errors in Drupal 10.0. The two issue might seem not to be related, only they both use the class variable
$this->prefixes. And the other issue needs to be fixed before the release of 9.0.Comment #18
andyposttest-only reroll for 9.0.x
Comment #20
andypostAdded related D7 issue to summary as well #1713332: The SQLite database driver fails to drop simpletest tables
Added related for blocker #3106531: Notify in Status Report that per-table database prefixes are no longer supported, and will throw errors in Drupal 10.0
As blocker targeted to 9.3 here could be workaround
Comment #21
andypostFix for fail-test (sqlite only) and patch with early fix
Comment #24
andypostD7 issue was commited with extra tests that could be forward-ported from #1713332: The SQLite database driver fails to drop simpletest tables