mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
Add multi-database data layer
Introduce aether-data-schema and driver-specific schema generation for Postgres, MySQL, and SQLite. Split data backends, lifecycle, repositories, and gateway runtime integration across database drivers. Verified with cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace.
This commit is contained in:
247
crates/aether-data/schema/compose_schema.sh
Normal file
247
crates/aether-data/schema/compose_schema.sh
Normal file
@@ -0,0 +1,247 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
schema_root="${root}/schema"
|
||||
driver_schema_root="${schema_root}/drivers"
|
||||
bootstrap_schema_root="${schema_root}/bootstrap/postgres"
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Usage:
|
||||
bash crates/aether-data/schema/compose_schema.sh split
|
||||
bash crates/aether-data/schema/compose_schema.sh generate
|
||||
bash crates/aether-data/schema/compose_schema.sh compose
|
||||
bash crates/aether-data/schema/compose_schema.sh check
|
||||
|
||||
split Regenerate schema source fragments from the current executable SQL.
|
||||
generate Generate SQL fragments from logical schema definitions.
|
||||
compose Rebuild executable SQL from schema source manifests.
|
||||
check Verify generated SQL is current, bootstrap sources are readable, and executable SQL matches manifests.
|
||||
USAGE
|
||||
}
|
||||
|
||||
generate_logical_schema() {
|
||||
(cd "${root}/../.." && cargo run -q -p aether-data-schema --bin aether-schema -- generate)
|
||||
}
|
||||
|
||||
check_logical_generated() {
|
||||
local args=()
|
||||
local path
|
||||
args+=(--require-tables-from "${root}/migrations/postgres/20260403000000_baseline.sql")
|
||||
for path in "${root}/migrations/mysql/"*.sql "${root}/migrations/sqlite/"*.sql; do
|
||||
[[ -f "${path}" ]] || continue
|
||||
args+=(--require-tables-from "${path}")
|
||||
done
|
||||
(cd "${root}/../.." && cargo run -q -p aether-data-schema --bin aether-schema -- check "${args[@]}")
|
||||
printf 'ok generated logical schema\n'
|
||||
}
|
||||
|
||||
manifest_path() {
|
||||
local target="$1"
|
||||
printf '%s/manifest.txt' "$(source_dir_path "${target}")"
|
||||
}
|
||||
|
||||
source_dir_path() {
|
||||
local target="$1"
|
||||
printf '%s/%s' "${driver_schema_root}" "${target}"
|
||||
}
|
||||
|
||||
output_path() {
|
||||
local target="$1"
|
||||
case "${target}" in
|
||||
postgres/baseline)
|
||||
printf '%s/migrations/postgres/20260403000000_baseline.sql' "${root}"
|
||||
;;
|
||||
mysql/baseline)
|
||||
printf '%s/migrations/mysql/20260403000000_baseline.sql' "${root}"
|
||||
;;
|
||||
sqlite/baseline)
|
||||
printf '%s/migrations/sqlite/20260403000000_baseline.sql' "${root}"
|
||||
;;
|
||||
*)
|
||||
printf 'unknown schema target: %s\n' "${target}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
write_manifest() {
|
||||
local target="$1"
|
||||
shift
|
||||
local manifest
|
||||
manifest="$(manifest_path "${target}")"
|
||||
mkdir -p "$(dirname "${manifest}")"
|
||||
: > "${manifest}"
|
||||
local part
|
||||
for part in "$@"; do
|
||||
printf '%s\n' "${part}" >> "${manifest}"
|
||||
done
|
||||
}
|
||||
|
||||
append_manifest() {
|
||||
local target="$1"
|
||||
shift
|
||||
local manifest
|
||||
manifest="$(manifest_path "${target}")"
|
||||
local part
|
||||
for part in "$@"; do
|
||||
printf '%s\n' "${part}" >> "${manifest}"
|
||||
done
|
||||
}
|
||||
|
||||
split_fragment() {
|
||||
local source="$1"
|
||||
local target="$2"
|
||||
local filename="$3"
|
||||
local start_line="$4"
|
||||
local end_line="$5"
|
||||
local output
|
||||
output="$(source_dir_path "${target}")/${filename}"
|
||||
|
||||
mkdir -p "$(dirname "${output}")"
|
||||
if [[ "${end_line}" == "EOF" ]]; then
|
||||
sed -n "${start_line},\$p" "${source}" > "${output}"
|
||||
else
|
||||
sed -n "${start_line},${end_line}p" "${source}" > "${output}"
|
||||
fi
|
||||
printf '%s: lines %s-%s\n' "${output#${root}/}" "${start_line}" "${end_line}"
|
||||
}
|
||||
|
||||
compose_target_to_stdout() {
|
||||
local target="$1"
|
||||
local manifest
|
||||
manifest="$(manifest_path "${target}")"
|
||||
if [[ ! -f "${manifest}" ]]; then
|
||||
printf 'missing schema manifest: %s\n' "${manifest}" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
local part
|
||||
while IFS= read -r part || [[ -n "${part}" ]]; do
|
||||
[[ -z "${part}" || "${part}" == \#* ]] && continue
|
||||
cat "$(source_dir_path "${target}")/${part}"
|
||||
done < "${manifest}"
|
||||
}
|
||||
|
||||
compose_target() {
|
||||
local target="$1"
|
||||
local output
|
||||
output="$(output_path "${target}")"
|
||||
compose_target_to_stdout "${target}" > "${output}"
|
||||
printf 'composed %s from %s\n' "${output#${root}/}" "$(manifest_path "${target}")"
|
||||
}
|
||||
|
||||
check_target() {
|
||||
local target="$1"
|
||||
local output tmp
|
||||
output="$(output_path "${target}")"
|
||||
tmp="$(mktemp)"
|
||||
compose_target_to_stdout "${target}" > "${tmp}"
|
||||
if ! diff -u "${output}" "${tmp}"; then
|
||||
rm -f "${tmp}"
|
||||
printf 'schema source does not match %s\n' "${output#${root}/}" >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -f "${tmp}"
|
||||
printf 'ok %s\n' "${target}"
|
||||
}
|
||||
|
||||
split_postgres_baseline() {
|
||||
local source="${root}/migrations/postgres/20260403000000_baseline.sql"
|
||||
local target="postgres/baseline"
|
||||
write_manifest "${target}" \
|
||||
"001_types_and_tables.sql" \
|
||||
"002_defaults.sql" \
|
||||
"003_constraints.sql" \
|
||||
"004_indexes.sql" \
|
||||
"005_foreign_keys.sql" \
|
||||
"006_footer.sql"
|
||||
split_fragment "${source}" "${target}" 001_types_and_tables.sql 1 1349
|
||||
split_fragment "${source}" "${target}" 002_defaults.sql 1350 1365
|
||||
split_fragment "${source}" "${target}" 003_constraints.sql 1366 2490
|
||||
split_fragment "${source}" "${target}" 004_indexes.sql 2491 3730
|
||||
split_fragment "${source}" "${target}" 005_foreign_keys.sql 3731 4582
|
||||
split_fragment "${source}" "${target}" 006_footer.sql 4583 EOF
|
||||
}
|
||||
|
||||
check_bootstrap_sources() {
|
||||
local manifest="${bootstrap_schema_root}/manifest.txt"
|
||||
local tmp
|
||||
tmp="$(mktemp)"
|
||||
|
||||
local part
|
||||
while IFS= read -r part || [[ -n "${part}" ]]; do
|
||||
[[ -z "${part}" || "${part}" == \#* ]] && continue
|
||||
cat "${bootstrap_schema_root}/${part}" >> "${tmp}"
|
||||
done < "${manifest}"
|
||||
|
||||
rm -f "${tmp}"
|
||||
printf 'ok bootstrap/postgres source\n'
|
||||
}
|
||||
|
||||
split_linear_baseline() {
|
||||
local driver="$1"
|
||||
local source="${root}/migrations/${driver}/20260403000000_baseline.sql"
|
||||
local target="${driver}/baseline"
|
||||
write_manifest "${target}" \
|
||||
"001_identity.sql" \
|
||||
"002_provider_catalog.sql" \
|
||||
"003_auth_config.sql" \
|
||||
"004_proxy_nodes.sql" \
|
||||
"005_wallet_billing.sql" \
|
||||
"006_usage.sql"
|
||||
|
||||
if [[ "${driver}" == "mysql" ]]; then
|
||||
split_fragment "${source}" "${target}" 001_identity.sql 1 121
|
||||
split_fragment "${source}" "${target}" 002_provider_catalog.sql 122 417
|
||||
split_fragment "${source}" "${target}" 003_auth_config.sql 418 487
|
||||
split_fragment "${source}" "${target}" 004_proxy_nodes.sql 488 527
|
||||
split_fragment "${source}" "${target}" 005_wallet_billing.sql 528 711
|
||||
split_fragment "${source}" "${target}" 006_usage.sql 712 EOF
|
||||
else
|
||||
split_fragment "${source}" "${target}" 001_identity.sql 1 117
|
||||
split_fragment "${source}" "${target}" 002_provider_catalog.sql 118 417
|
||||
split_fragment "${source}" "${target}" 003_auth_config.sql 418 485
|
||||
split_fragment "${source}" "${target}" 004_proxy_nodes.sql 486 525
|
||||
split_fragment "${source}" "${target}" 005_wallet_billing.sql 526 728
|
||||
split_fragment "${source}" "${target}" 006_usage.sql 729 EOF
|
||||
fi
|
||||
}
|
||||
|
||||
targets=(
|
||||
"postgres/baseline"
|
||||
"mysql/baseline"
|
||||
"sqlite/baseline"
|
||||
)
|
||||
|
||||
cmd="${1:-}"
|
||||
case "${cmd}" in
|
||||
split)
|
||||
split_postgres_baseline
|
||||
split_linear_baseline mysql
|
||||
split_linear_baseline sqlite
|
||||
;;
|
||||
generate)
|
||||
generate_logical_schema
|
||||
;;
|
||||
compose)
|
||||
for target in "${targets[@]}"; do
|
||||
compose_target "${target}"
|
||||
done
|
||||
;;
|
||||
check)
|
||||
check_logical_generated
|
||||
check_bootstrap_sources
|
||||
for target in "${targets[@]}"; do
|
||||
check_target "${target}"
|
||||
done
|
||||
;;
|
||||
-h|--help|help|"")
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user