124 lines
3.2 KiB
Bash
Executable File
124 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Apply / drop ClickHouse DDL files in alphabetical order.
|
|
#
|
|
# Usage:
|
|
# clickhouse_apply.sh up apply *.up.sql in infra/clickhouse/
|
|
# clickhouse_apply.sh down apply *.down.sql in REVERSE order
|
|
#
|
|
# Talks to the HTTP(S) interface via curl -- no clickhouse-client binary needed.
|
|
# The SQL is POSTed as the raw body; ClickHouse parses the body when the URL
|
|
# has no ?query= parameter.
|
|
#
|
|
# Env:
|
|
# CLICKHOUSE_ADDR (default localhost:8123)
|
|
# CLICKHOUSE_DB (default cdp)
|
|
# CLICKHOUSE_USER (default default)
|
|
# CLICKHOUSE_PASSWORD (default empty)
|
|
# CLICKHOUSE_SECURE (default 0; auto-on for port 8443)
|
|
|
|
set -euo pipefail
|
|
|
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/clickhouse"
|
|
ADDR="${CLICKHOUSE_ADDR:-localhost:8123}"
|
|
DB="${CLICKHOUSE_DB:-cdp}"
|
|
USER="${CLICKHOUSE_USER:-default}"
|
|
PASS="${CLICKHOUSE_PASSWORD:-}"
|
|
SECURE="${CLICKHOUSE_SECURE:-0}"
|
|
|
|
MODE="${1:-up}"
|
|
|
|
host="${ADDR%%:*}"
|
|
port="${ADDR##*:}"
|
|
|
|
case "$SECURE" in
|
|
1|true|TRUE|yes) scheme="https" ;;
|
|
*) [[ "$port" == "8443" ]] && scheme="https" || scheme="http" ;;
|
|
esac
|
|
|
|
URL_BASE="${scheme}://${host}:${port}/"
|
|
|
|
# post_sql posts a SQL string to ClickHouse. The query goes in the request
|
|
# body; URL params can carry session options like ?database=foo.
|
|
post_sql() {
|
|
local sql="$1"
|
|
local extra_param="${2:-}"
|
|
local url="$URL_BASE"
|
|
[[ -n "$extra_param" ]] && url="${URL_BASE}?${extra_param}"
|
|
printf '%s' "$sql" | curl -sS --fail-with-body \
|
|
-u "${USER}:${PASS}" \
|
|
--data-binary @- \
|
|
"$url"
|
|
echo
|
|
}
|
|
|
|
post_sql_file() {
|
|
# ClickHouse HTTP rejects multi-statements; split the file by `;` and post
|
|
# each statement individually. Our DDL files use `--` line comments and
|
|
# do not contain literal `;` inside strings, so a naive RS split is safe.
|
|
local file="$1"
|
|
local extra_param="${2:-}"
|
|
local url="$URL_BASE"
|
|
[[ -n "$extra_param" ]] && url="${URL_BASE}?${extra_param}"
|
|
|
|
local tmpdir
|
|
tmpdir=$(mktemp -d)
|
|
|
|
awk -v dir="$tmpdir" '
|
|
BEGIN { RS=";" ; count=0 }
|
|
{
|
|
stmt=$0
|
|
gsub(/^[[:space:]\n\r]+|[[:space:]\n\r]+$/, "", stmt)
|
|
if (stmt == "") next
|
|
count++
|
|
out=sprintf("%s/%04d.sql", dir, count)
|
|
print stmt > out
|
|
}
|
|
' "$file"
|
|
|
|
local rc=0
|
|
local s
|
|
for s in "$tmpdir"/*.sql; do
|
|
[[ -f "$s" ]] || continue
|
|
if ! curl -sS --fail-with-body \
|
|
-u "${USER}:${PASS}" \
|
|
--data-binary "@${s}" \
|
|
"$url"; then
|
|
rc=1
|
|
break
|
|
fi
|
|
echo
|
|
done
|
|
rm -rf "$tmpdir"
|
|
return "$rc"
|
|
}
|
|
|
|
ensure_db() {
|
|
post_sql "CREATE DATABASE IF NOT EXISTS \`${DB}\`"
|
|
}
|
|
|
|
run_sql_file() {
|
|
local file="$1"
|
|
echo ">>> applying $(basename "$file")"
|
|
post_sql_file "$file" "database=${DB}"
|
|
}
|
|
|
|
case "$MODE" in
|
|
up)
|
|
ensure_db
|
|
for f in $(ls "$DIR"/*.up.sql 2>/dev/null | sort); do
|
|
run_sql_file "$f"
|
|
done
|
|
;;
|
|
down)
|
|
for f in $(ls "$DIR"/*.down.sql 2>/dev/null | sort -r); do
|
|
run_sql_file "$f"
|
|
done
|
|
;;
|
|
*)
|
|
echo "usage: $0 {up|down}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo "done."
|