public function tag($table) { foreach ($this->sourceBucket as &$entry1) { if (is_null($entry1)) { continue; } foreach ($this->targetBucket as &$entry2) { if (is_null($entry2)) { continue; } if ($this->isKeyEqual($entry1, $entry2)) { // unset the fields to ignore $params = ParamsFactory::get(); if (isset($params->fieldsToIgnore[$table])) { foreach ($params->fieldsToIgnore[$table] as $fieldToIgnore) { unset($entry1[$fieldToIgnore]); unset($entry2[$fieldToIgnore]); } } $differ = new MapDiffer(); $diff = $differ->doDiff($entry2, $entry1); if (!empty($diff)) { $this->diffBucket[] = ['keys' => array_only($entry1, $this->key), 'diff' => $diff]; } $entry1 = null; $entry2 = null; } } } }
function getDiff() { $params = ParamsFactory::get(); $diffSequence = []; // Tables $tableData = new TableData($this->manager); $sourceTables = $this->manager->getTables('source'); $targetTables = $this->manager->getTables('target'); if (isset($params->tablesToIgnore)) { $sourceTables = array_diff($sourceTables, $params->tablesToIgnore); $targetTables = array_diff($targetTables, $params->tablesToIgnore); } $commonTables = array_intersect($sourceTables, $targetTables); foreach ($commonTables as $table) { try { $diffs = $tableData->getDiff($table); $diffSequence = array_merge($diffSequence, $diffs); } catch (DataException $e) { Logger::error($e->getMessage()); } } $addedTables = array_diff($sourceTables, $targetTables); foreach ($addedTables as $table) { $diffs = $tableData->getNewData($table); $diffSequence = array_merge($diffSequence, $diffs); } $deletedTables = array_diff($targetTables, $sourceTables); foreach ($deletedTables as $table) { $diffs = $tableData->getOldData($table); $diffSequence = array_merge($diffSequence, $diffs); } return $diffSequence; }
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; }
public function run() { // Increase memory limit ini_set('memory_limit', '512M'); try { // Params $paramsFactory = new ParamsFactory(); $params = $paramsFactory->get(); // Diff $diffCalculator = new DiffCalculator(); $diff = $diffCalculator->getDiff($params); // Empty diff if (empty($diff['schema']) && empty($diff['data'])) { Logger::info("Identical resources"); } else { // SQL $sqlGenerator = new SQLGenerator($diff); $up = ''; $down = ''; if ($params->include !== 'down') { $up = $sqlGenerator->getUp(); } if ($params->include !== 'up') { $down = $sqlGenerator->getDown(); } // Generate $templater = new Templater($params, $up, $down); $templater->output(); } Logger::success("Completed"); } catch (\Exception $e) { if ($e instanceof BaseException) { Logger::error($e->getMessage(), true); } else { Logger::error("Unexpected error: "); throw $e; } } }
function getDiff() { $params = ParamsFactory::get(); $diffs = []; // Collation $dbName = $this->manager->getDB('target')->getDatabaseName(); $sourceCollation = $this->getDBVariable('source', 'collation_database'); $targetCollation = $this->getDBVariable('target', 'collation_database'); if ($sourceCollation !== $targetCollation) { $diffs[] = new SetDBCollation($dbName, $sourceCollation, $targetCollation); } // Charset $sourceCharset = $this->getDBVariable('source', 'character_set_database'); $targetCharset = $this->getDBVariable('target', 'character_set_database'); if ($sourceCharset !== $targetCharset) { $diffs[] = new SetDBCharset($dbName, $sourceCharset, $targetCharset); } // Tables $tableSchema = new TableSchema($this->manager); $sourceTables = $this->manager->getTables('source'); $targetTables = $this->manager->getTables('target'); if (isset($params->tablesToIgnore)) { $sourceTables = array_diff($sourceTables, $params->tablesToIgnore); $targetTables = array_diff($targetTables, $params->tablesToIgnore); } $addedTables = array_diff($sourceTables, $targetTables); foreach ($addedTables as $table) { $diffs[] = new AddTable($table, $this->manager->getDB('source')); } $commonTables = array_intersect($sourceTables, $targetTables); foreach ($commonTables as $table) { $tableDiff = $tableSchema->getDiff($table); $diffs = array_merge($diffs, $tableDiff); } $deletedTables = array_diff($targetTables, $sourceTables); foreach ($deletedTables as $table) { $diffs[] = new DropTable($table, $this->manager->getDB('target')); } return $diffs; }