Files
moonwell-core/import-custom-sql.sh
2026-05-06 23:26:10 +04:00

312 lines
9.7 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
if [[ -f "$ENV_FILE" ]]; then
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
fi
IMPORT_MYTHICPLUS_SQL="${ACORE_IMPORT_MYTHICPLUS_SQL:-1}"
IMPORT_STORE_SQL="${ACORE_IMPORT_STORE_SQL:-1}"
IMPORT_ENCOUNTER_JOURNAL_SQL="${ACORE_IMPORT_ENCOUNTER_JOURNAL_SQL:-1}"
usage() {
cat <<EOF
Usage: $(basename "$0")
Imports required custom SQL that lives outside the normal AzerothCore module paths.
Currently this bootstraps the MythicPlus and Store Lua packages, plus module strings
that are not covered by the normal module SQL import path in this deployment.
EOF
}
log() {
printf '[import-custom-sql] %s\n' "$*"
}
mysql_query() {
local database="$1"
local sql="$2"
docker compose exec -T ac-database bash -lc \
"mysql -N -s -uroot -p\"\$MYSQL_ROOT_PASSWORD\" \"$database\"" <<<"$sql"
}
mysql_exec() {
local database="${1:-}"
local sql="$2"
if [[ -n "$database" ]]; then
docker compose exec -T ac-database bash -lc \
"mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\" \"$database\"" <<<"$sql"
else
docker compose exec -T ac-database bash -lc \
"mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\"" <<<"$sql"
fi
}
table_exists() {
local database="$1"
local table_name="$2"
local result
result="$(mysql_query "information_schema" \
"SELECT COUNT(*) FROM tables WHERE table_schema = '${database}' AND table_name = '${table_name}';")"
[[ "$result" == "1" ]]
}
database_exists() {
local database="$1"
local result
result="$(mysql_query "information_schema" \
"SELECT COUNT(*) FROM schemata WHERE schema_name = '${database}';")"
[[ "$result" == "1" ]]
}
import_sql_file() {
local database="$1"
local file_path="$2"
if [[ ! -f "$file_path" ]]; then
printf 'SQL file not found: %s\n' "$file_path" >&2
exit 1
fi
log "importing $(basename "$file_path") into ${database}"
docker compose exec -T ac-database bash -lc \
"mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\" \"$database\"" < "$file_path"
}
require_integer_flag() {
local name="$1"
local value="$2"
if ! [[ "$value" =~ ^[01]$ ]]; then
printf '%s must be 0 or 1, got: %s\n' "$name" "$value" >&2
exit 1
fi
}
maybe_import_table() {
local database="$1"
local table_name="$2"
local file_path="$3"
if table_exists "$database" "$table_name"; then
log "table ${database}.${table_name} already exists, skipping"
return 0
fi
import_sql_file "$database" "$file_path"
}
import_mythicplus_sql() {
if [[ "$IMPORT_MYTHICPLUS_SQL" == "0" ]]; then
log "MythicPlus SQL import disabled, skipped"
return 0
fi
if [[ ! -d "$ROOT_DIR/sql/Mythic+" ]]; then
log "sql/Mythic+ directory not found, skipped"
return 0
fi
maybe_import_table "acore_characters" "character_mythic_history" \
"$ROOT_DIR/sql/Mythic+/characters/character_mythic_history.sql"
maybe_import_table "acore_characters" "character_mythic_keys" \
"$ROOT_DIR/sql/Mythic+/characters/character_mythic_keys.sql"
maybe_import_table "acore_characters" "character_mythic_rating" \
"$ROOT_DIR/sql/Mythic+/characters/character_mythic_rating.sql"
maybe_import_table "acore_characters" "character_mythic_vault" \
"$ROOT_DIR/sql/Mythic+/characters/character_mythic_vault.sql"
maybe_import_table "acore_characters" "character_mythic_weekly_affixes" \
"$ROOT_DIR/sql/Mythic+/characters/character_mythic_weekly_affixes.sql"
maybe_import_table "acore_world" "world_mythic_loot" \
"$ROOT_DIR/sql/Mythic+/world/world_mythic_loot.sql"
maybe_import_table "acore_world" "world_vault_loot" \
"$ROOT_DIR/sql/Mythic+/world/world_vault_loot.sql"
if [[ "$(mysql_query "acore_world" "
SELECT
CASE
WHEN EXISTS (SELECT 1 FROM creature_template WHERE entry = 900001)
AND EXISTS (SELECT 1 FROM item_template WHERE entry = 900100)
AND EXISTS (SELECT 1 FROM gameobject_template WHERE entry = 900000)
AND EXISTS (SELECT 1 FROM creature WHERE id1 = 900001 OR id2 = 900001 OR id3 = 900001)
AND EXISTS (SELECT 1 FROM gameobject WHERE id = 900000)
THEN 1
ELSE 0
END;
")" == "0" ]]; then
log "repairing MythicPlus world bootstrap entries"
mysql_exec "acore_world" "
DELETE FROM creature WHERE id1 = 900001 OR id2 = 900001 OR id3 = 900001;
DELETE FROM gameobject WHERE id = 900000;
DELETE FROM creature_template_locale WHERE entry = 900001;
DELETE FROM item_template_locale WHERE ID = 900100;
DELETE FROM creature_template_model WHERE CreatureID = 900001;
DELETE FROM creature_template WHERE entry = 900001;
DELETE FROM item_template WHERE entry = 900100;
DELETE FROM gameobject_template WHERE entry = 900000;
"
import_sql_file "acore_world" "$ROOT_DIR/sql/Mythic+/world/creature_and_keystones.sql"
else
log "MythicPlus creature bootstrap already exists, skipping"
fi
}
import_store_sql() {
local store_sql_file="$ROOT_DIR/sql/Store.sql"
local temp_sql=""
if [[ "$IMPORT_STORE_SQL" == "0" ]]; then
log "Store SQL import disabled, skipped"
return 0
fi
if [[ ! -d "$ROOT_DIR/lua_scripts/Store_System" ]]; then
log "lua_scripts/Store_System directory not found, skipped"
return 0
fi
if [[ ! -f "$store_sql_file" ]]; then
log "sql/Store.sql not found, skipped"
return 0
fi
if ! database_exists "store"; then
log "creating database store"
mysql_exec "" "CREATE DATABASE IF NOT EXISTS \`store\` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
fi
temp_sql="$(mktemp)"
{
printf 'CREATE DATABASE IF NOT EXISTS `store` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;\n'
printf 'USE `store`;\n'
awk '
BEGIN { skip = 0 }
skip {
if ($0 ~ /;[[:space:]]*$/) {
skip = 0
}
next
}
$0 ~ /^INSERT INTO `store_logs` / {
skip = 1
next
}
{
sub(/^INSERT INTO /, "INSERT IGNORE INTO ")
print
}
' "$store_sql_file"
} > "$temp_sql"
log "bootstrapping store database"
mysql_exec "" "$(cat "$temp_sql")"
rm -f "$temp_sql"
}
import_aoe_loot_sql() {
local aoe_loot_sql_file="$ROOT_DIR/modules/mod-aoe-loot/data/sql/db-world/base/aoe_loot_module_string.sql"
if [[ ! -f "$aoe_loot_sql_file" ]]; then
log "mod-aoe-loot module string SQL not found, skipped"
return 0
fi
if [[ "$(mysql_query "acore_world" "SELECT COUNT(*) FROM module_string WHERE module = 'mod-aoe-loot';")" != "0" ]] && \
[[ "$(mysql_query "acore_world" "SELECT COUNT(*) FROM module_string_locale WHERE module = 'mod-aoe-loot';")" != "0" ]]; then
log "mod-aoe-loot module strings already exist, skipping"
return 0
fi
import_sql_file "acore_world" "$aoe_loot_sql_file"
}
import_encounter_journal_sql() {
local schema_file="$ROOT_DIR/modules/mod-encounter-journal/data/sql/db-world/base/01_encounter_journal_schema.sql"
local sample_file="$ROOT_DIR/modules/mod-encounter-journal/data/sql/db-world/base/02_encounter_journal_sample.sql"
if [[ "$IMPORT_ENCOUNTER_JOURNAL_SQL" == "0" ]]; then
log "Encounter Journal SQL import disabled, skipped"
return 0
fi
if [[ ! -f "$schema_file" ]]; then
log "mod-encounter-journal schema SQL not found, skipped"
return 0
fi
# Schema file uses CREATE TABLE IF NOT EXISTS, but we still gate on the
# canonical tier table to avoid noisy re-imports on every bootstrap.
if ! table_exists "acore_world" "custom_ej_tier"; then
import_sql_file "acore_world" "$schema_file"
else
log "custom_ej_* schema already present, skipping"
fi
# Sample data only on a fresh install (no rows in any custom_ej_* table).
# Re-running it would clobber hand-edited rows in the 9000-9999 id range.
if [[ -f "$sample_file" ]]; then
local total
total="$(mysql_query "acore_world" "
SELECT (SELECT COUNT(*) FROM custom_ej_tier)
+ (SELECT COUNT(*) FROM custom_ej_instance)
+ (SELECT COUNT(*) FROM custom_ej_encounter)
+ (SELECT COUNT(*) FROM custom_ej_creature)
+ (SELECT COUNT(*) FROM custom_ej_section)
+ (SELECT COUNT(*) FROM custom_ej_loot);
")"
if [[ "$total" == "0" ]]; then
import_sql_file "acore_world" "$sample_file"
else
log "custom_ej_* tables already populated, skipping sample data"
fi
fi
}
if (($# > 0)); then
case "$1" in
-h|--help)
usage
exit 0
;;
*)
printf 'Unknown option: %s\n\n' "$1" >&2
usage >&2
exit 1
;;
esac
fi
require_integer_flag "ACORE_IMPORT_MYTHICPLUS_SQL" "$IMPORT_MYTHICPLUS_SQL"
require_integer_flag "ACORE_IMPORT_STORE_SQL" "$IMPORT_STORE_SQL"
require_integer_flag "ACORE_IMPORT_ENCOUNTER_JOURNAL_SQL" "$IMPORT_ENCOUNTER_JOURNAL_SQL"
cd "$ROOT_DIR"
if ! docker compose ps --status running --services | grep -qx 'ac-database'; then
printf 'ac-database is not running. Start the database first.\n' >&2
exit 1
fi
import_mythicplus_sql
import_aoe_loot_sql
import_encounter_journal_sql
import_store_sql
log "custom SQL bootstrap completed"