Files
intaleq/backend/scripts/apply_sql_tolerant.sh
T
Hamza-Ayed 8df0f92fcf 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.
2026-07-29 17:04:05 +03:00

54 lines
2.1 KiB
Bash
Executable File

#!/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"