Run migrate/fresh more than once.
Command should run on each call.
On second call an exception is thrown because the migration table gets not created after truncate.
| Q | A
| ---------------- | ---
| Yii version | 2.0.13
| PHP version | 7.0.18
| Operating system | Debian
The error was introduced in Yii 2.0.13.
The reason is the implementation of db/Schema::getTableMetadata(). The migration table does not exist but it's schema information are still present in file cache.
This is the current implementation:
if ($refresh || !isset($this->_tableMetadata[$name])) {
...
}
if (!array_key_exists($type, $this->_tableMetadata[$name])) {
...
}
And it should look like this:
if (!isset($this->_tableMetadata[$name])) {
...
}
if ($refresh || !array_key_exists($type, $this->_tableMetadata[$name])) {
...
}
Em. yii\db\Schema::refreshTableSchema will be used in yii\console\controllers\MigrateController::truncateDatabase() and should take care of it.
The current implementation should work fine because it discards a complete table metadata if $refresh is true.
What's the database used? MySQL?
Yes, MySQL.
The current implementation should work fine because it discards a complete table metadata if $refresh is true.
@sergeymakinen
No, it does not work "fine".
use yii\console\controllers\MigrateController,
yii\db\Connection,
yii\db\Schema,
yii\db\TableSchema;
MigrateController::truncateDatabase() gets table names from Schema::getTableSchemas(), where the TableSchema::$name for the migrations table is plain migration (or {prefix}migration if current Connection::$tablePrefix is {prefix}). The metadata for this table name is discarded.
But MigrateController::getMigrationHistory(), which is called when migrating up, gets the metadata for MigrateController::$migrationTable, defined as {{%migration}} by default. If the metadata for this table name is cached, Schema::getTableMetadata() will return that regardless of the value of $refresh (and the actual schema state). That's what this issue is all about.
I suppose a solution would involve tuning table prefix resolution for schema caching and/or migrations.
@U-D13 thanks for details. It's definitely not okay.
But caching/purging logic is still the same from the old Schema, so it this issue probably existed for some time before.
Anyway I will dig into this.
I confirm this.
An issue resides in yii\db\Schema::getCacheKey it was there for a long time:
a cache key doesn't resolve table names to raw names, so {{%table}} and table entries are stored/deleted as is.
I will add tests and fix it tonight.
This error is still present in the latest version. Running migrate/up once, then dropping/recreating db and running migrate/up again results in error because its still cached. The solution proposed in the original post fixes it and seems logical to me.
Most helpful comment
@U-D13 thanks for details. It's definitely not okay.
But caching/purging logic is still the same from the old
Schema, so it this issue probably existed for some time before.Anyway I will dig into this.