Problem/Motivation
#2613878: Use hash for Migration source keys, rather than verbatim values introduced a query in \Drupal\migrate\Plugin\migrate\id_map\Sql::delete() that required the source_ids_hash column to exist:
$message_query = $this->getDatabase()->delete($this->messageTableName());
$message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values));
$message_query->execute();
However, an update hook was not added to the module to ensure that any existing message tables include the column. For scenarios where a site is doing incremental updates from a previous version of drupal, doing a re-install & fresh install of migrate isn't really a good option. Even though migrate is experimental, updates have been written in the past and this can be easily fixed with such an approach.
Proposed resolution
Create an update hook to ensure that the columns exist on any table(s) that already exist in the database.
Remaining tasks
- Write Patch
User interface changes
N/A
API changes
N/A
Data model changes
Data model already changed, need to update existing database schema.
| Comment | File | Size | Author |
|---|---|---|---|
| #47 | migration_failed_with-2679797-8.0.x-47.patch | 9.35 KB | mikgreen |
| #47 | migration_failed_with-2679797-47.patch | 11.75 KB | mikgreen |
| #39 | migration_failed_with-2679797-39.patch | 12.24 KB | hkirsman |
| #32 | migration_failed_with-2679797-32.patch | 12.23 KB | jcnventura |
| #32 | interdiff.txt | 315 bytes | jcnventura |
Comments
Comment #2
davidwbarratt commentedComment #3
davidwbarratt commentedComment #4
edysmpWorking
Comment #5
edysmpComment #6
edysmpComment #7
davidwbarratt commentedShouldn't it be:
Instead of:
Other than that, it looks perfect to me.
Comment #8
edysmpI think this
$this->messageTableName()causes a loop:Comment #9
davidwbarratt commentedAh, that makes sense.
Comment #10
davidwbarratt commentedI get this error when running the tests locally:
Comment #11
davidwbarratt commentedLooks like it's because of this:
I guess we should first add a check to ensure that the table actually exists?
Comment #13
davidwbarratt commentedComment #14
davidwbarratt commentedComment #15
davidwbarratt commentedComment #16
davidwbarratt commentedComment #18
benjy commentedCould this be in an update hook rather than in the map itself?
Comment #19
heddnI remember asking this in irc at one point and someone mentioned that since migrate was an experimental module, an update wasn't necessary. If we think about it, it isn't just the creation of the column we need to worry about. We also need to worry about the change of the PK and the fact that all lookups are now done by a hash. So, all previous messages (and mappings) would need to go into that hook update and do a one-time hash into the hash column, right?
Comment #20
davidwbarratt commented#18,
I think it probably should be, but there is already code in there to take care of missing fields for the map tables, so to me it makes sense that it's all together one way or another.
Comment #21
davidwbarratt commented#19,
If a module in core isn't going to have an upgrade path from one Drupal release to another, it probably shouldn't be in core at all.
Either that, or it should be really really clear that experimental modules do not have an upgrade path from version to version and therefor should never be used. If that is the case, then I don't see how anyone can migrate to Drupal 8 until MIgrate is no longer experimental.
However, I think providing an upgrade path is somewhat trivial (especially in this case), and should be done. To your point, it would make more sense to have an update hook than do what this patch does, but similar code already exists in the method, so we should probably remove both instances.
Perhaps we should make a follow up issue? Or fix it all in this issue? How would we figure out all the tables we need to update?
Comment #22
davidwbarratt commentedYou're right, there's a bigger issue where you can't run
migrate-import --updateyou get a nasty gram error like this:I've attached a patch that's an update script that updates all of the existing tables, rather than having them in
::ensureTablesComment #23
heddnComment #24
heddnComment #25
heddnOK, we should write an update test here. And we'll need a test where the db table was created using a version of drupal < 8.0.5. Not sure how to do that. I guess we could create the table and fabricate the data in the test. Is there a standard way to do this?
I'm guessing there is a way to stub out the db table in phpunit.
Comment #26
davidwbarratt commentedTake a look at:
\Drupal\Tests\migrate\Unit\MigrateSqlIdMapEnsureTablesTest::testEnsureTablesExist()
Comment #27
davidwbarratt commentedNeed to remove the existing source id's from the message table(s).
Comment #28
benjy commentedWhat happens if the migrate module isn't even enabled, will this fatal?
Comment #29
davidwbarratt commentedIs it possible to run an hook_update without the same module being enabled?
Comment #30
benjy commentedah yeah of course. Patch looks good, just needs a test.
Comment #31
freelock@davidwbarratt it was possible in D7 and earlier, if a module was installed but disabled... (though module updates in this state often fail).
Does this patch require the tip of 8.0.x or 8.1.x?
I just tried applying to 8.0.5 and it fails to apply changes to the tests. Ignored those and attempted to run the update and I got:
PHP Fatal error: Class 'Unicode' not found in /var/www/html/asap/d8/core/modules/migrate/migrate.install on line 44
Comment #32
jcnventuraIndeed, there's a missing Unicode class.. This patch adds it.
Comment #33
usrsbn commentedHi,
I applied patch 32. After that i uninstalled and reinstalled migrate, migrate_upgrade and migrate_drupal. When trying to "Rerun" import via UI (/upgrade) I get the following errors:
Warning: mt_rand(): max(-1) is smaller than min(0) in Drupal\Core\Database\Database::parseConnectionInfo() (line 217 of core/lib/Drupal/Core/Database/Database.php).Notice: Undefined offset: 0 in Drupal\Core\Database\Database::parseConnectionInfo() (line 217 of core/lib/Drupal/Core/Database/Database.php).Notice: Undefined index: driver in Drupal\Core\Database\Database::openConnection() (line 369 of core/lib/Drupal/Core/Database/Database.php).Notice: Undefined index: driver in Drupal\migrate_upgrade\Form\MigrateUpgradeForm->validateCredentialForm() (line 986 of modules/migrate_upgrade/src/Form/MigrateUpgradeForm.php).Resolve the issue below to continue the upgrade. Driver not specified for this database connection: upgradeI have not specified a database called "upgrade". This is what's in my settings.php:
Do you have any idea how I can fix this?
Comment #34
heddn#33 is unrelated to this issue. Please open as a separate thing.
Comment #35
usrsbn commentedThanks! I posted the issue here.
Comment #36
ckngApplied patch #32. Importing new content give me Integrity constraint violation, on 2 migrations tested.
Comment #38
ckngRe-tested my case in #36 after apply only the db update code in the patch without the unit tests. It works for new migration, but still fail for
migrate-import --updateAre there specific step required? Uninstall migrate? Rollback all migrations?
Comment #39
hkirsman commentedNeeded patch for 8.1.0
Comment #40
hkirsman commentedRe-uploading correct version
Comment #43
mikeryanThe idmap plugin has this code already, you can just call $map->mapTableName() and $map->messageTableName(). Note that in theory one could swap in their own idmap plugin and use a different scheme for naming tables.
What does this have to do with the issue?
Comment #44
smazI've had this issue after upgrading from Drupal 8.0.3 -> 8.0.6.
I applied the patch in #40 (had to remove core/modules/user/tests/src/Kernel/Migrate/d6/MigrateUserProfileValuesTest.php part as that file doesn't exist in 8.0.6), and it's worked fine for me - thanks all.
Comment #45
hkirsman commentedI have no idea of why there's something in the patch and I don't have the technical know-how. Just adjusted the patch for last Drupal :)
Anybody can answer mikeryan?
Comment #46
mikgreen commentedThe version from #40, just without MigrateUserProfileValuesTest.php part.
Comment #47
mikgreen commentedI've had a case where there are source_ids_hash fields, but their empty.
So I changed the code to always regenerate source_ids_hash field values.
Also removed stuff as per #43.
Also a patch for 8.0.x is included.
Comment #48
mikeryanComment #51
smazI had the same - the patch added the new column, but all values were empty so any migrations that used the migration process plugin failed to lookup the value from the other migrations.
I've applied the 8.0.x patch from #47 & it applies cleanly, adds the new column + generates the source_ids_hash value.
Cheers
Comment #52
Anonymous (not verified) commentedAt the migrate critical issues triage in New Orleans we decided to remove the critical tag on this issue for the same reasons @heddn suggests in #19. We are keeping the issue open as a major so that work can proceed.
Comment #53
tom m fallon commentedHello
We are having some real trouble upgrading from 8.0.x to 8.1.x
I've added an 8.1.8 core, connected to a 8.0.x database.
I've successfully applied patch #47 migration_failed_with-2679797-47.patch
And received the following error.
The line that appears to be wrong is
migrate.install
Has anyone else got this issue, and if possible how do I resolve it. I believe this is a critical issue as its preventing users from reliably upgrading to 8.1.x leaving them running out of date software.
Thanks
Comment #54
tom m fallon commentedComment #55
tom m fallon commentedI've elevated this issue to critical from major.
I've done some further work with this issue, and found the migrate_plus is a particular source of the issue. It appears to be the lack the getSourcePlugin which is loaded within
This issue blocks us from being able to move to Drupal 8.1.x.
I believe the issue is a widespread thing, and to de-escalate the issue a patch which reliably works is provided, and preferably merged into the migrate module. If we are to use a hash it should be that the upgrade path to 8.1.x is possible.
This issue hasn't moved in months, and needs to be addressed if people are to want to upgrade to the later versions of Drupal.
I will be following this issue closely, and any ways to get this turned round into production ready code I'm happy to help.
Comment #56
mikeryanAs previously mentioned, experimental modules are not required to provide update paths (although it may be nice to do so in some cases, like this) - moving back to major.
The problem you're seeing is that the last patch was made before #2625696: Make migrations themselves plugins instead of config entities went in (see the change record). That patch removed migration configuration entities from core - since migrate_plus added its own implementation of migration configuration entities on the contrib side, the old update function here is picking those up, but too much has changed since 8.0.x for that to work cleanly. If you didn't have migrate_plus, the update function would have done nothing at all.
So, the update function here would need to use the core migration plugin manager instead of trying to load config entities. That probably won't work until #2560795: Source plugins have a hidden dependency on migrate_drupal is fixed - well, maybe it would work if you have migrate_drupal enabled, but not in the general case.
I'm sorry, but about all I can suggest in the short term is a custom script to update the tables.
As for the patch itself:
Comment #58
heddnDiscussed in weekly migrate meeting. Considering this is for functionality added in 8.0.x, and we are now in 8.2.x we are going to mark this "not fix". There were no promises that updates would be provided for experimental modules and no one has stepped forward to provide such an update.