// 校验合并后的 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(' '));