SQL解析异常问题:WHERE子句未完成全部条件解析
问题分析与解决方案
你的问题核心在于逻辑运算符(AND/OR)在语法中的层级设计错误,导致无法支持多个连续的逻辑条件组合。让我一步步拆解问题并给出修复方案:
问题根源
你当前的语法将AND/OR放在了common_clause_token中,作为expression_tail的一部分,而expression的定义是:
expression: expression_body (expression_tail)* ;
这种结构存在致命缺陷:
- 一个
expression只能是以expression_body开头,后面跟着若干个expression_tail(比如比较操作、IN、LIKE,或者你的AND+表达式) - 当解析完
(NS1.Func1(...) == false) AND (String.IsNullOrEmpty(...))后,整个结构已经是一个完整的expression(expression_body(...) + expression_tail(AND + expression(...))) - 但第二个
AND需要连接的是前一个完整的expression,而不是某个expression_body,原语法无法识别这种链式逻辑连接,因此在遇到第二个AND时直接报错。
修复方案
重构语法层级,将逻辑运算符(AND/OR)提升到expression的顶层,让它专门负责连接多个独立的条件表达式。具体修改如下:
调整后的核心语法片段
where_clause: WHERE expression ; // 顶层表达式,负责逻辑连接 expression: logical_expression ; // 逻辑表达式:多个比较表达式用AND/OR连接,支持任意数量的链式组合 logical_expression: comparison_expression ( (AND | OR) comparison_expression )* ; // 单个条件表达式(包含原来的expression_body和尾部修饰) comparison_expression: expression_body (expression_tail)* ; // 保持原来的expression_body定义不变 expression_body: DEFAULT | STAR | NULL | func_call | BETWEEN expression AND expression | IF LPAREN expression COMMA expression COMMA expression RPAREN | windowing_func | EXISTS LPAREN select_query RPAREN | LPAREN expression RPAREN | identifier_up_to_two_parts | CHAR | NUMBER | STRING ; // 调整expression_tail:移除common_clause_token中的AND/OR,逻辑连接移到顶层处理 expression_tail: comparison_operator expression | comparison_operator (ALL | SOME | ANY) LPAREN select_query RPAREN | IN LPAREN expression ( COMMA expression )* RPAREN | IS (NOT)? NULL | NOT? LIKE expression ( ESCAPE expression )? | /* 移除AND/OR后的 */ common_clause_token expression ; // 修正common_clause_token:去掉AND/OR,避免层级混淆 common_clause_token: NUMBER | CHAR | UNQUOTEDIDENTIFIER | PUNCTUATION | KEYWORD | STAR | DOT | LT | EQ | GT | Q | LBRKT | RBRKT ;
为什么这样能解决问题
修改后的语法层级更清晰合理:
comparison_expression专注处理单个独立条件(比如括号里的函数调用、比较判断)logical_expression允许用AND/OR连接任意多个comparison_expression,完美支持链式逻辑组合- 你的WHERE子句
(...) AND (...) AND (...)会被正确解析为3个comparison_expression通过两次AND连接,解析树会完整包含所有条件,不会在第二个AND处提前终止。
验证你的输入
调整语法后,你的目标SQL语句:
SELECT col1, col2, col3 FROM T1 WHERE (NS1.Func1(col1, 123) == false) AND (String.IsNullOrEmpty(Func2(col2))) AND (NOT (NS2.Func3(col3) == "1")) ;
将可以被正常解析,完全符合你的预期。
内容的提问来源于stack exchange,提问作者Jeff Saremi
相关产品推荐
相关产品推荐

