fix(migration): apply schema fixes statement-by-statement, tolerating already-applied changes
The bulk `mysql < file.sql` run aborted on the first "duplicate column" error because some columns from an earlier partial run already existed. apply_sql_tolerant.sh now runs each ALTER separately and only skips MySQL errors 1060/1061/1091/1050 (duplicate column/key, missing to drop, table exists) — any other error still stops the migration immediately.
This commit is contained in:
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# apply_sql_tolerant.sh — يطبّق ملف SQL عبارة-عبارة، ويتجاوز فقط
|
||||
# أخطاء "الشيء موجود مسبقاً" (عمود/فهرس/جدول مكرّر) لأن هذا يعني
|
||||
# أن المايغريشن طُبِّقت جزئياً من قبل — أي خطأ آخر يوقف التنفيذ فوراً.
|
||||
#
|
||||
# الاستخدام:
|
||||
# bash apply_sql_tolerant.sh <container> <root_pw> <db> <file.sql>
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
CONTAINER="$1" ROOT_PW="$2" DB="$3" FILE="$4"
|
||||
DC="docker compose -f $(cd "$(dirname "${BASH_SOURCE[0]}")/../../docker" && pwd)/docker-compose.yml"
|
||||
|
||||
# أكواد MySQL التي تعني "طُبِّق هذا الجزء من قبل" ولا خطر في تجاوزها:
|
||||
# 1060 Duplicate column 1061 Duplicate key 1091 Can't DROP (missing)
|
||||
# 1050 Table already exists
|
||||
TOLERATED='1060|1061|1091|1050'
|
||||
|
||||
# نفصل على ';' في نهاية السطر — كل ALTER/عبارة في هذا الملف على أسطرها
|
||||
# الخاصة أصلاً، وما من ; داخل نص أو تعليق يكسر هذا التقسيم هنا.
|
||||
STATEMENT=""
|
||||
FAILED=0
|
||||
APPLIED=0
|
||||
SKIPPED=0
|
||||
|
||||
while IFS= read -r line; do
|
||||
# تجاهل التعليقات المستقلة والأسطر الفارغة قبل تجميع أي عبارة
|
||||
[[ "$line" =~ ^[[:space:]]*--.*$ ]] && continue
|
||||
[[ -z "${line// }" ]] && continue
|
||||
|
||||
STATEMENT+="$line"$'\n'
|
||||
|
||||
if [[ "$line" == *";" ]]; then
|
||||
OUT=$($DC exec -T "$CONTAINER" mysql -uroot -p"$ROOT_PW" "$DB" -e "$STATEMENT" 2>&1) && {
|
||||
APPLIED=$((APPLIED+1))
|
||||
} || {
|
||||
if echo "$OUT" | grep -qE "ERROR ($TOLERATED)"; then
|
||||
SKIPPED=$((SKIPPED+1))
|
||||
echo " … skipped (already applied): $(echo "$STATEMENT" | head -1 | cut -c1-70)"
|
||||
else
|
||||
echo "✘ FAILED on statement:"
|
||||
echo "$STATEMENT"
|
||||
echo "$OUT"
|
||||
FAILED=1
|
||||
fi
|
||||
}
|
||||
STATEMENT=""
|
||||
[[ "$FAILED" == "1" ]] && exit 1
|
||||
fi
|
||||
done < "$FILE"
|
||||
|
||||
echo " ✔ applied=$APPLIED skipped(already-present)=$SKIPPED"
|
||||
@@ -143,11 +143,12 @@ $DC exec -T mysql mysqldump -uroot -p"$ROOT_PW" --single-transaction --routines
|
||||
echo " ✔ $(du -h "$BACKUP" | cut -f1)"
|
||||
|
||||
# ── 5) إصلاحات المخطط ───────────────────────────────────────
|
||||
# تُطبَّق عبارة-عبارة وتتجاوز فقط "موجود مسبقاً" — يجعل التشغيل قابلاً
|
||||
# لإعادة المحاولة إن كانت المايغريشن قد طُبِّقت جزئياً من قبل.
|
||||
echo
|
||||
echo "── [5/8] applying schema fixes"
|
||||
$DC exec -T mysql mysql -uroot -p"$ROOT_PW" "$DST_DB" \
|
||||
< "$REPO/backend/migrations/2026_07_29_v2_migration_schema_fixes.sql"
|
||||
echo " ✔ applied"
|
||||
bash "$REPO/backend/scripts/apply_sql_tolerant.sh" mysql "$ROOT_PW" "$DST_DB" \
|
||||
"$REPO/backend/migrations/2026_07_29_v2_migration_schema_fixes.sql"
|
||||
|
||||
# ── 6) فحص المفتاح ──────────────────────────────────────────
|
||||
echo
|
||||
|
||||
Reference in New Issue
Block a user