public function getChangeDiff($table, $key)
{
$params = ParamsFactory::get();
$diffSequence = [];
$db1 = $this->source->getDatabaseName();
$db2 = $this->target->getDatabaseName();
$columns1 = $this->manager->getColumns('source', $table);
$columns2 = $this->manager->getColumns('target', $table);
if (isset($params->fieldsToIgnore[$table])) {
$columns1 = array_diff($columns1, $params->fieldsToIgnore[$table]);
$columns2 = array_diff($columns2, $params->fieldsToIgnore[$table]);
}
$wrapAs = function ($arr, $p1, $p2) {
return array_map(function ($el) use($p1, $p2) {
return "`{$p1}`.`{$el}` as `{$p2}{$el}`";
}, $arr);
};
$wrapCast = function ($arr, $p) {
return array_map(function ($el) use($p) {
return "CAST(`{$p}`.`{$el}` AS CHAR CHARACTER SET utf8)";
}, $arr);
};
$columnsAas = implode(',', $wrapAs($columns1, 'a', 's_'));
$columnsA = implode(',', $wrapCast($columns1, 'a'));
$columnsBas = implode(',', $wrapAs($columns2, 'b', 't_'));
$columnsB = implode(',', $wrapCast($columns2, 'b'));
$keyCols = implode(' AND ', array_map(function ($el) {
return "a.{$el} = b.{$el}";
}, $key));
$this->source->setFetchMode(\PDO::FETCH_NAMED);
$result = $this->source->select("SELECT * FROM (\n SELECT {$columnsAas}, {$columnsBas}, MD5(concat({$columnsA})) AS hash1,\n MD5(concat({$columnsB})) AS hash2 FROM {$db1}.{$table} as a \n INNER JOIN {$db2}.{$table} as b \n ON {$keyCols}\n ) t WHERE hash1 <> hash2");
$this->source->setFetchMode(\PDO::FETCH_ASSOC);
foreach ($result as $row) {
$diff = [];
$keys = [];
foreach ($row as $k => $value) {
if (starts_with($k, 's_')) {
$theKey = substr($k, 2);
$targetKey = 't_' . $theKey;
$sourceValue = $value;
if (in_array($theKey, $key)) {
$keys[$theKey] = $value;
}
if (isset($row[$targetKey])) {
$targetValue = $row[$targetKey];
if ($sourceValue != $targetValue) {
$diff[$theKey] = new \Diff\DiffOp\DiffOpChange($targetValue, $sourceValue);
}
} else {
$diff[$theKey] = new \Diff\DiffOp\DiffOpChange(NULL, $sourceValue);
}
}
}
$diffSequence[] = new UpdateData($table, ['keys' => $keys, 'diff' => $diff]);
}
return $diffSequence;
}