云
2026-09-29 f87ce86307056f63f79312178037cc8714eb2b13
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
// 校验合并后的 SQL 文件:语句切分、引号闭合、括号平衡、首关键字白名单
const fs = require('node:fs');
// 先剔除整行注释(本文件中注释均为整行,且注释内会出现示例 SQL 的分号)
const raw = fs.readFileSync(__dirname + '/config_export_all_20260928.sql', 'utf8');
const s = raw
  .split(/\r?\n/)
  .filter((l) => !l.trimStart().startsWith('--'))
  .join('\n');
 
let inS = false;
let start = 0;
let depth = 0;
let maxDepth = 0;
let statements = 0;
const keywords = new Set();
const ESC = '\\';
 
for (let i = 0; i < s.length; i++) {
  const c = s[i];
  if (!inS) {
    if (c === "'") {
      inS = true;
    } else if (c === '(') {
      depth++;
      if (depth > maxDepth) maxDepth = depth;
    } else if (c === ')') {
      depth--;
      if (depth < 0) throw new Error(`第 ${i} 字符处括号提前闭合`);
    } else if (c === ';') {
      const st = s.slice(start, i).trim();
      if (st) {
        const body = st
          .split(/\r?\n/)
          .filter((l) => l.trim() && !l.trim().startsWith('--'))
          .join('\n');
        const m = body.match(/^(\w+)/);
        if (!m) throw new Error(`语句无法识别首关键字:${st.slice(0, 80)}`);
        keywords.add(m[1].toUpperCase());
        statements++;
      }
      start = i + 1;
    }
  } else if (c === "'") {
    if (s[i - 1] === ESC && s[i - 2] !== ESC) {
      // 反斜杠转义的引号,仍在字符串内
    } else if (s[i + 1] === "'") {
      i++; // '' 转义
    } else {
      inS = false;
    }
  }
}
 
console.log('语句数     :', statements);
console.log('括号结尾深度:', depth, '(应为 0)');
console.log('最大嵌套深度:', maxDepth);
console.log('未闭合字符串:', inS, '(应为 false)');
console.log('首关键字集合:', [...keywords].sort().join(' '));