validate.sh
3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env bash
# validate.sh — 校验 V1.sql 与 docs/03 的两个集合一致性:
# 维度 1: 表名集合
# 维度 2: 每张共有表的列名集合
#
# 用法: bash validate.sh <V1.sql> <docs/03 path>
# 退出码:
# 0 = 一致
# 1 = 不一致(差异明细打印到 stderr)
# 2 = 用法错误(路径找不到等)
set -uo pipefail
export LC_ALL=C # sort / comm 行为确定
V1=${1:?missing V1 sql path}
DOC=${2:?missing docs/03 path}
[ -f "$V1" ] || { echo "validate.sh: V1 not found: $V1" >&2; exit 2; }
[ -f "$DOC" ] || { echo "validate.sh: docs not found: $DOC" >&2; exit 2; }
ERR=0
# ─── 维度 1: 表名集合 ───────────────────────────────────────────
TABLES_DOC=$(grep -E '^## `[^`]+`' "$DOC" \
| sed -E 's/^## `([^`]+)`.*/\1/' | sort -u)
TABLES_SQL=$(grep -E '^CREATE TABLE `[^`]+`' "$V1" \
| sed -E 's/^CREATE TABLE `([^`]+)`.*/\1/' | sort -u)
ONLY_DOC=$(comm -23 <(echo "$TABLES_DOC") <(echo "$TABLES_SQL"))
ONLY_SQL=$(comm -13 <(echo "$TABLES_DOC") <(echo "$TABLES_SQL"))
if [ -n "$ONLY_DOC" ] || [ -n "$ONLY_SQL" ]; then
{
echo "=== 维度 1: 表名集合不一致 ==="
[ -n "$ONLY_DOC" ] && { echo " docs/03 有但 V1 无:"; echo "$ONLY_DOC" | sed 's/^/ - /'; }
[ -n "$ONLY_SQL" ] && { echo " V1 有但 docs/03 无:"; echo "$ONLY_SQL" | sed 's/^/ - /'; }
} >&2
ERR=1
# 表数差异 → 不再做列校验
exit 1
fi
# ─── 维度 2: 每张共有表的列名集合 ──────────────────────────────
COMMON=$(comm -12 <(echo "$TABLES_DOC") <(echo "$TABLES_SQL"))
extract_doc_cols() {
local table=$1
awk -v t="$table" '
$0 ~ "^## `" t "`" { in_table=1; in_fields=0; next }
in_table && /^## `/ { exit }
in_table && /^### 字段/ { in_fields=1; next }
in_table && in_fields && /^###/ { in_fields=0 }
in_table && in_fields && /^\|/ {
n = split($0, a, "|")
gsub(/^[ ]+|[ ]+$/, "", a[2])
gsub(/`/, "", a[2])
if (a[2] != "" && a[2] != "字段" && a[2] !~ /^-+$/) print a[2]
}
' "$DOC" | sort -u
}
extract_sql_cols() {
local table=$1
awk -v t="$table" '
$0 ~ "^CREATE TABLE `" t "`" { in_table=1; next }
in_table && /^\)/ { in_table=0; next }
in_table && /^[[:space:]]*`[^`]+`/ \
&& $0 !~ /^[[:space:]]*(PRIMARY|UNIQUE|KEY|FOREIGN|CONSTRAINT|INDEX)/ {
match($0, /`[^`]+`/)
print substr($0, RSTART+1, RLENGTH-2)
}
' "$V1" | sort -u
}
while IFS= read -r t; do
[ -z "$t" ] && continue
D_COLS=$(extract_doc_cols "$t")
S_COLS=$(extract_sql_cols "$t")
ONLY_D=$(comm -23 <(echo "$D_COLS") <(echo "$S_COLS"))
ONLY_S=$(comm -13 <(echo "$D_COLS") <(echo "$S_COLS"))
if [ -n "$ONLY_D" ] || [ -n "$ONLY_S" ]; then
{
echo "=== 维度 2: 表 \`$t\` 列名不一致 ==="
[ -n "$ONLY_D" ] && { echo " docs/03 有但 V1 无:"; echo "$ONLY_D" | sed 's/^/ - /'; }
[ -n "$ONLY_S" ] && { echo " V1 有但 docs/03 无:"; echo "$ONLY_S" | sed 's/^/ - /'; }
} >&2
ERR=1
fi
done <<< "$COMMON"
if [ $ERR -ne 0 ]; then
exit 1
fi
echo "validate.sh: ✓ 表名集合 + 每表列名集合 与 docs/03 一致"
exit 0