When using Migration::DESTINATION system-of-record for updating existing commerce products, the database gives me following errors:

WD commerce_product: PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect decimal value: '' for column
'field_ratio_value' at row 1: INSERT INTO {field_data_field_ratio} (entity_type, entity_id, revision_id, bundle, delta,
language, field_ratio_value) 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] => commerce_product
    [:db_insert_placeholder_1] => 14
    [:db_insert_placeholder_2] => 14
    [:db_insert_placeholder_3] => product
    [:db_insert_placeholder_4] => 0
    [:db_insert_placeholder_5] => und
    [:db_insert_placeholder_6] => 
)
 in field_sql_storage_field_storage_write() (line 424 of
/www/site-one/modules/field/modules/field_sql_storage/field_sql_storage.module).

Basically, the problem is that running the "prepare" hook on existing field instances of an existing entity wraps the field values into yet another array, which breaks saving the entity. The solution that worked for me is running the "prepare" hook only on added/updated fields and not the whole updated entity. See the attached patch.

Comments

bojanz’s picture

Is this today's -dev? I committed a fix by drewish on the 25th aimed at fixing a similar error.

jelenex’s picture

Yeah, just tested with the latest -dev, the error is still there. The problem does look similar to #1282562: Allow updating entity records, but the cause seems to be different. Also it manifests itself only on the field values that are attached to entity, not the entity's own attributes (like title, sku etc).

drewish’s picture

Humm... it seems like if I was using the prepare there I'd want it to have the complete entity, not just the new fields. Slight tangent: one thing I do like with the node destination that it doesn't seem like Entity API destination does is let you unset fields by providing empty mappings.

So is it MigrateFieldsEntityHandler::prepare() that's doing this or more MigrateValueFieldHandler::prepare()? I was wondering how Migrate's destinations for Node/User deal with this:

    if ($migration->getSystemOfRecord() == Migration::DESTINATION) {
      if (!isset($node->nid)) {
        throw new MigrateException(t('System-of-record is DESTINATION, but no destination nid provided'));
      }
      $old_node = node_load($node->nid);
      if (!isset($node->created)) {
        $node->created = $old_node->created;
      }
      if (!isset($node->vid)) {
        $node->vid = $old_node->vid;
      }
      if (!isset($node->status)) {
        $node->status = $old_node->status;
      }
      if (!isset($node->uid)) {
        $node->uid = $old_node->uid;
      }
    }
# ...
    // Invoke migration prepare handlers
    $this->prepare($node, $row);
# ... 
    // Trying to update an existing node
    if ($migration->getSystemOfRecord() == Migration::DESTINATION) {
      // Incoming data overrides existing data, so only copy non-existent fields
      foreach ($old_node as $field => $value) {
        // An explicit NULL in the source data means to wipe to old value (i.e.,
        // don't copy it over from $old_node)
        if (property_exists($node, $field) && $node->$field === NULL) {
          // Ignore this field
        }
        elseif (!isset($node->$field)) {
          $node->$field = $old_node->$field;
        }
      }
    }
  

So it looks like they copy over critical id properties, then run prepare, then copy over any unchanged stuff. Seems to make sense to me.

pcambra’s picture

Not exactly the same issue, but came across something similar with prepare() doing weird stuff with the fields of the resulting entity when using destination as system of a record.

I solved it just by invoking the prepare in the "new" entity and merge it with the old afterwards. Patch attached.

pcambra’s picture

Status: Needs review » Reviewed & tested by the community

Ooops, just noticed the patch in #0, sorry :)

It's just the same thing, I'm marking this RTBC

amateescu’s picture

Status: Reviewed & tested by the community » Closed (duplicate)

The Entity API migration class has been moved to Migrate Extras, so I included this fix in the patch from #1530848: Entity API plugin: various cleanups and improvements.