Skip to content

fix(parser): #283 collect errors from all erroneous statements in multi-statement input#470

Open
liuxy0551 wants to merge 2 commits into
DTStack:nextfrom
liuxy0551:fix_283
Open

fix(parser): #283 collect errors from all erroneous statements in multi-statement input#470
liuxy0551 wants to merge 2 commits into
DTStack:nextfrom
liuxy0551:fix_283

Conversation

@liuxy0551
Copy link
Copy Markdown
Collaborator

@liuxy0551 liuxy0551 commented May 12, 2026

  1. 某些语句遇到错误没有全部捕获 #283

简介

问题原因

当输入 SELEC * from table1; SELEC * from table2; 时:

  1. SELEC 不是合法关键字,被词法分析器识别为 ID 类型(token 889)
  2. while 循环检查 LA(1)(即当前 token),发现 ID(889)不在位掩码中
  3. 循环体根本不执行,直接跳到 match(EOF)
  4. match(EOF) 发现当前 token 不是 EOF,抛出异常
  5. catch 块捕获异常,调用 reportError() 报告一个错误
  6. 调用 recover() 消费掉所有剩余 token 直到 EOF
  7. 方法返回,第二个 SELEC 语句的错误被完全吞掉了

简单来说:当 SQL 语句以拼写错误的关键词开头时,解析器根本不尝试解析后续语句,直接把后面所有内容都跳过了,所以只能报出一个错误。

修复方案

validate() 方法中增加了一个"分而治之"的策略:

  1. 先用原始方式解析整个输入,拿到初始错误列表
  2. 如果有错误,且输入中包含多个 ; 分隔的语句,则按 ; 拆分输入
  3. 对每个语句片段独立创建解析器进行验证
  4. 只有当拆分验证发现的错误多于原始解析时,才使用拆分的结果

这样做的好处是:

  • 修复了问题:SELEC * from t1; SELEC * from t2; 现在能正确报出 2 个错误
  • 不影响正常 SQL:原始解析成功时(0 个错误)不会触发拆分逻辑
  • 兼容 BEGIN...END 块:不会错误地拆分 BEGIN STATEMENT SET; ... END; 这类跨分号的语法结构

monaco-sql-languages 使用 dt-sql-parser@4.5.0-beta.3 即可预览效果,因此不再单独提供 PR 和预览地址。

image

遗留点

借助分号进行切分,如果 SQL 语句没有写分号,依旧会报一个错。没有分号的多条语句此时校验优先级不高,暂不处理。

@liuxy0551 liuxy0551 requested a review from Cythia828 May 12, 2026 03:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant