Change source id mapping of a Drupal 8 migration

Posted by patrick on Wed, 12/13/2017 - 06:57

Drupal Core's Migrate API maintains an internal table mapping unique source ids to destination ids. This is usually done via a database table that holds the field values that together uniquely identify a source row and the matching destination id of the entity in Drupal. The field names and types that uniquely identify a source row are provided by the source plugin of a migration. In most cases, you just have some kind of an id column, but migrate supports any number of fields for the primary key of the source row.

Recently I was dealing with a migration that was using the Url source plugin provided by Migrate Plus to import files from an XML source. The source plugins provided by Migrate Plus allow you to specify the ids returned by MigrateSourceInterface::getIds() in the YML file of your migrations. Originally I used a simple id map like this:

source:
  ids:
    id:
      type: integer

Unfortunately, I later noticed that I needed to add the file name as a second key to the id map, so I changed the YML file to something like this:

  ids:
    id:
      type: integer
    file_name:
      type: string

So far so good. When I wanted to update the migration, I was greeted by this error message:

Migration failed with source plugin exception: SQLSTATE[42S22]: Column not found: 1054 Unknown column "sourceid2" in
"field list": INSERT INTO {migrate_map_example_file} (source_ids_hash, sourceid1, sourceid2, source_row_status,
rollback_action, hash, last_imported) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6); Array
(
    [:db_insert_placeholder_0] => a8d0cbb8ca5f48c73993244fd275342d84b92a2eb33300b0852ef560f70aa55d
    [:db_insert_placeholder_1] => 10817
    [:db_insert_placeholder_2] =>
    [:db_insert_placeholder_3] => 2
    [:db_insert_placeholder_4] => 0
    [:db_insert_placeholder_5] =>
    [:db_insert_placeholder_6] => 1513082182
)  

Solving this is actually way easier than I thought. Just drop the migrate mapping table for your migration from the SQL database:

DROP TABLE migrate_map_example_file;

If you are less adventurous, you might just want to rename the table initially:

RENAME TABLE migrate_map_example_file TO migrate_map_example_file_backup;

As soon as you rerun your migration, migrate will recreate the table for you, this time using the new id mapping. Voilá.

Systems
Drupal 8/9