#!/bin/bash -eu function merge_dbs { # Takes file name as only argument function check_for_diff_errors { if grep -q '^<<<<<<<' $1; then echo "ERROR: The merged database contains conficts." echo " Please search the $1 file for the occurrence of '^<<<<<<<' and resolve the conflicts manually." echo "Did you fix the conflicts? (yes/no)" read if [ "$REPLY" = yes ] then check_for_diff_errors $1 else echo "Cannot continue without a merged database. Exiting." exit 1 fi fi } DB1=$(readlink -vnf $1) LAST_MERGE_DB=$(readlink -vnf $2) DB2=$(readlink -vnf $3) touch $4 DEST=$(readlink -vnf $4) mkdir -p merge_dbs cd merge_dbs # Strip all data and comments DATA_PATTERN="INSERT INTO .* VALUES" COMMENTS_PATTERN='..!40103 SET TIME_ZONE=@OLD_TIME_ZONE ..;\|..!40101 SET SQL_MODE=@OLD_SQL_MODE ..;\|..!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS ..;\|..!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS ..;\|..!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT ..;\|..!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS ..;\|..!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION ..;\|..!40111 SET SQL_NOTES=@OLD_SQL_NOTES ..;\|Dump completed on' SED_STRIP_AUTO_INCREMENT="s/\().*\) AUTO_INCREMENT=[0-9]\+\(.*\)/\1\2/" echo "Merging the new schema structure..." grep -v "${DATA_PATTERN}\|${COMMENTS_PATTERN}" $DB1 | sed "$SED_STRIP_AUTO_INCREMENT" > db1_schema.sql grep -v "${DATA_PATTERN}\|${COMMENTS_PATTERN}" $LAST_MERGE_DB | sed "$SED_STRIP_AUTO_INCREMENT" > last_merge_schema.sql grep -v "${DATA_PATTERN}\|${COMMENTS_PATTERN}" $DB2 | sed "$SED_STRIP_AUTO_INCREMENT" > db2_schema.sql # Save the comments; to be appended to the final merged file later grep "${COMMENTS_PATTERN}" $DB2 > comments.sql # Build the new schema structure if ! diff3 -E --merge db1_schema.sql last_merge_schema.sql db2_schema.sql > merged_schema.sql then check_for_diff_errors 'merged_schema.sql' fi # List tables in the new schema FILTERED_TABLES="cache\|sessions\|history\|watchdog" # table list ignore some talbes just the name + \| remove line breaks and last \| characters MERGED_SCHEMA_TABLES=`cat merged_schema.sql | grep 'CREATE TABLE ' | grep -v "$FILTERED_TABLES" | sed 's/CREATE TABLE \`\(.*\)\` (/\1\\\|/g' | tr -d '\n' | sed 's/..$//'` # Get data for the new schema tables, keeping the locks, but not disabling keys since we actually want to perform integrity check when we insert the data grep '\(LOCK TABLES.*\|..!40000 ALTER TABLE .* DISABLE KEYS ..;\|INSERT INTO `\('${MERGED_SCHEMA_TABLES}'\)` VALUES\|..!40000 ALTER TABLE .* ENABLE KEYS ..;\|UNLOCK TABLES.*\)' $DB1 > db1_filtered_data.sql grep '\(LOCK TABLES.*\|..!40000 ALTER TABLE .* DISABLE KEYS ..;\|INSERT INTO `\('${MERGED_SCHEMA_TABLES}'\)` VALUES\|..!40000 ALTER TABLE .* ENABLE KEYS ..;\|UNLOCK TABLES.*\)' $LAST_MERGE_DB > last_merge_filtered_data.sql grep '\(LOCK TABLES.*\|..!40000 ALTER TABLE .* DISABLE KEYS ..;\|INSERT INTO `\('${MERGED_SCHEMA_TABLES}'\)` VALUES\|..!40000 ALTER TABLE .* ENABLE KEYS ..;\|UNLOCK TABLES.*\)' $DB2 > db2_filtered_data.sql echo "Merging the new database data..." # Merge the data if ! diff3 -E --merge db1_filtered_data.sql last_merge_filtered_data.sql db2_filtered_data.sql > merged_data.sql then check_for_diff_errors 'merged_data.sql' fi echo "Combining schema structure and data..." # Append the data and the comments to the schema cat merged_data.sql >> merged_schema.sql cat comments.sql >> merged_schema.sql # We're done mv merged_schema.sql $DEST cd .. rm -rf merge_dbs }