You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using a DatabaseTruncation trait, the tests will fail if a DB connection is configured to prefix all the tables with following errror:
Illuminate\Database\QueryException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'laravel.foo_foo_failed_jobs' doesn't exist (Connection: mysql, SQL: select exists(select * from `foo_foo_failed_jobs`) as `exists`)
It would seem that when trying to check which tables to truncate, the trait loads table names (which include prefix) via DoctrineSchemaManager and then calls\Illuminate\Database\Query\Builder::truncate which appends the prefix once again.
As a quick and dirty workaround I've implemented custom trait, that overrides \Illuminate\Foundation\Testing\DatabaseTruncation::truncateTablesForConnection method:
<?phpnamespaceApp\Tests;
useIlluminate\Database\Connection;
useIlluminate\Database\ConnectionInterface;
useIlluminate\Foundation\Testing\DatabaseTruncationasBaseDatabaseTruncation;
/** * This trait is a workaround for a bug, where DatabaseTruncation trait would attempt to truncate * a table with prefix being applied twice (i.e. foo_foo_TableName when connection prefix is set to 'foo') */traitDatabaseTruncation
{
useBaseDatabaseTruncation;
protectedfunctiontruncateTablesForConnection(ConnectionInterface$connection, ?string$name): void
{
$dispatcher = $connection->getEventDispatcher();
$connection->unsetEventDispatcher();
collect(static::$allTables[$name] ??= $connection->getDoctrineSchemaManager()->listTableNames())
->when(
property_exists($this, 'tablesToTruncate'),
fn ($tables) => $tables->intersect($this->tablesToTruncate),
fn ($tables) => $tables->diff($this->exceptTables($name))
)
->map(fn ($table) => self::SanitizeTableName($table, $connection)) // THISISWHATHASBEENADDED!!!
->filter(fn ($table) => $connection->table($table)->exists())
->each(fn ($table) => $connection->table($table)->truncate());
$connection->setEventDispatcher($dispatcher);
}
privatestaticfunctionSanitizeTableName(string$tableName, ConnectionInterface$connection): string
{
/** * We need to strip the table prefix from tableName, because doctrineSchemaManager * returns `foo_TableName` instead of `TableName`. * Without this, laravel will try to truncate `foo_foo_TableName` as it applies prefix once again * when it compiles a query */if (!$connection instanceof Connection) {
// we don't have access to prefix - return $tableName as it wasreturn$tableName;
}
$prefix = $connection->getTablePrefix();
// replace only$pos = strpos($tableName, $prefix);
if ($pos !== 0) {
// we do not want to replace substring that looks like prefix but is not onereturn$tableName;
}
returnsubstr_replace($tableName, '', $pos, strlen($prefix));
}
}
The fix unfortunately relies on concrete implementation of ConnectionInterface to access the getTablePrefix method.
Steps To Reproduce
Set up a database connection with prefix set to foo_
Add doctrine/dbal package for tests to work
Create a test class with two scenarios
Add DatabaseTruncation trait to newly created test class
As Laravel is an open source project, we rely on the community to help us diagnose and fix issues as it is not possible to research and fix every issue reported to us via GitHub.
If possible, please make a pull request fixing the issue you have described, along with corresponding tests. All pull requests are promptly reviewed by the Laravel team.
Thank you!
mobidev86
added a commit
to mobidev86/laravel-framework
that referenced
this issue
Sep 4, 2023
Laravel Version
10.21.1
PHP Version
8.2.9
Database Driver & Version
MariaDB 10.4 via docker
Description
When using a
DatabaseTruncation
trait, the tests will fail if a DB connection is configured to prefix all the tables with following errror:It would seem that when trying to check which tables to truncate, the trait loads table names (which include prefix) via
DoctrineSchemaManager
and then calls\Illuminate\Database\Query\Builder::truncate
which appends the prefix once again.As a quick and dirty workaround I've implemented custom trait, that overrides
\Illuminate\Foundation\Testing\DatabaseTruncation::truncateTablesForConnection
method:The fix unfortunately relies on concrete implementation of
ConnectionInterface
to access thegetTablePrefix
method.Steps To Reproduce
prefix
set tofoo_
doctrine/dbal
package for tests to workDatabaseTruncation
trait to newly created test classSee bsacharski/truncate-bug-report@4008a7a for a commit with changes that trigger the issue.
Expected outcome: tests should simply pass
Actual outcome: tests fail with following error:
The text was updated successfully, but these errors were encountered: