#!/usr/bin/env bash set -euo pipefail usage() { cat <<'EOF' Usage: migrate_workbench_tables.sh --host HOST --port PORT --user USER --password PASSWORD --source meeting_im --target workbench [--backup-dir DIR] Migrates im_workbench-owned tables from the shared IM database into the standalone workbench database. The target tables are dropped and recreated from the source dump. Source and target table dumps are written before any target changes. EOF } HOST="" PORT="3306" USER="" PASSWORD="" SOURCE_DB="meeting_im" TARGET_DB="workbench" BACKUP_DIR="" while [[ $# -gt 0 ]]; do case "$1" in --host) HOST="$2"; shift 2 ;; --port) PORT="$2"; shift 2 ;; --user) USER="$2"; shift 2 ;; --password) PASSWORD="$2"; shift 2 ;; --source) SOURCE_DB="$2"; shift 2 ;; --target) TARGET_DB="$2"; shift 2 ;; --backup-dir) BACKUP_DIR="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) echo "unknown argument: $1" >&2; usage >&2; exit 2 ;; esac done if [[ -z "$HOST" || -z "$USER" || -z "$PASSWORD" || -z "$SOURCE_DB" || -z "$TARGET_DB" ]]; then usage >&2 exit 2 fi TABLES=( im_workbench_apps im_org_departments im_org_members im_org_visibility_overrides im_attendance_rules im_attendance_shifts im_attendance_records im_attendance_checkins im_attendance_appeals im_meetings im_meeting_participants im_meeting_note_files im_daily_reports im_monthly_reports im_mailbox_config im_mailbox_submissions im_feedback_config im_feedback_submissions wb_ai_capability_config wb_ai_document wb_ai_idempotency_record wb_ai_meeting_summary wb_ai_prompt_template wb_ai_record wb_ai_table_analysis wb_ai_task wb_ai_task_step wb_ai_usage_log ) timestamp="$(date +%Y%m%d%H%M%S)" if [[ -z "$BACKUP_DIR" ]]; then BACKUP_DIR="./tmp/workbench_migration_${HOST}_${PORT}_${timestamp}" fi mkdir -p "$BACKUP_DIR" MYSQL=(mysql -h "$HOST" -P "$PORT" -u "$USER" "-p$PASSWORD" --default-character-set=utf8mb4) MYSQLDUMP=(mysqldump -h "$HOST" -P "$PORT" -u "$USER" "-p$PASSWORD" --default-character-set=utf8mb4 --single-transaction --skip-add-locks --set-gtid-purged=OFF) echo "backup dir: $BACKUP_DIR" echo "checking source tables..." "${MYSQL[@]}" -N -e "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='${SOURCE_DB}'" > "$BACKUP_DIR/${SOURCE_DB}_tables.txt" existing_tables=() for table in "${TABLES[@]}"; do if grep -qx "$table" "$BACKUP_DIR/${SOURCE_DB}_tables.txt"; then existing_tables+=("$table") else echo "warning: source table ${SOURCE_DB}.${table} does not exist, skipping" >&2 fi done if [[ ${#existing_tables[@]} -eq 0 ]]; then echo "no source tables found" >&2 exit 1 fi echo "creating target database if needed..." "${MYSQL[@]}" -e "CREATE DATABASE IF NOT EXISTS \`${TARGET_DB}\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci" echo "backing up source tables..." "${MYSQLDUMP[@]}" "$SOURCE_DB" "${existing_tables[@]}" > "$BACKUP_DIR/${SOURCE_DB}_workbench_tables.sql" target_existing=() for table in "${existing_tables[@]}"; do if "${MYSQL[@]}" -N -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='${TARGET_DB}' AND TABLE_NAME='${table}'" | grep -qx "1"; then target_existing+=("$table") fi done if [[ ${#target_existing[@]} -gt 0 ]]; then echo "backing up existing target tables..." "${MYSQLDUMP[@]}" "$TARGET_DB" "${target_existing[@]}" > "$BACKUP_DIR/${TARGET_DB}_workbench_tables_before.sql" fi drop_sql="SET FOREIGN_KEY_CHECKS=0;" for table in "${existing_tables[@]}"; do drop_sql+="DROP TABLE IF EXISTS \`${TARGET_DB}\`.\`${table}\`;" done drop_sql+="SET FOREIGN_KEY_CHECKS=1;" echo "dropping target tables..." "${MYSQL[@]}" -e "$drop_sql" echo "importing source dump into target..." sed -E \ -e "s/^\s*CREATE DATABASE .*//" \ -e "s/^\s*USE \`${SOURCE_DB}\`;//" \ -e "s/^\s*USE ${SOURCE_DB};//" \ -e "/^\s*LOCK TABLES /d" \ -e "/^\s*UNLOCK TABLES;/d" \ "$BACKUP_DIR/${SOURCE_DB}_workbench_tables.sql" | "${MYSQL[@]}" "$TARGET_DB" echo "row count comparison:" printf "%-34s %12s %12s\n" "table" "source" "target" failed=0 for table in "${existing_tables[@]}"; do src_count="$("${MYSQL[@]}" -N -e "SELECT COUNT(*) FROM \`${SOURCE_DB}\`.\`${table}\`")" dst_count="$("${MYSQL[@]}" -N -e "SELECT COUNT(*) FROM \`${TARGET_DB}\`.\`${table}\`")" printf "%-34s %12s %12s\n" "$table" "$src_count" "$dst_count" if [[ "$src_count" != "$dst_count" ]]; then failed=1 fi done | tee "$BACKUP_DIR/row_counts.txt" if [[ "$failed" -ne 0 ]]; then echo "row count mismatch" >&2 exit 1 fi echo "migration complete"