使用pyparsing解析含括号谓词的嵌套SQL查询求助
问题原因
原有解析逻辑失效的核心原因是infixNotation默认会将所有括号优先识别为逻辑表达式的分组边界,之前定义的字符集匹配规则优先级低于内置的括号分组逻辑,因此解析到第一个闭合括号时就判定第一个逻辑分组结束,直接截断了后续内容,且C In ("a", "b")内部的括号被误判为逻辑分组符,导致整个谓词被拆分。
修复方案
核心思路是先定义合法的原子谓词匹配规则,让解析器优先识别完整谓词(包括谓词内部带引号的字符串、配对的括号块),仅将不属于谓词内部的括号识别为逻辑分组边界,完整可运行代码如下:
from pyparsing import * # 匹配双引号包裹的字符串,支持转义字符 quoted_str = QuotedString('"', escChar='\\') # 定义逻辑运算符关键字,提前避免被识别为谓词内容 AND = CaselessKeyword("AND") OR = CaselessKeyword("OR") logical_op = AND | OR # 匹配普通词:非逻辑关键字、不含括号的可打印字符 normal_word = ~logical_op + Word(printables, excludeChars="()") # 递归匹配谓词内部的配对括号块 pred_paren = Forward() pred_atom = quoted_str | normal_word | pred_paren pred_paren <<= "(" + ZeroOrMore(pred_atom) + ")" # 单个完整谓词:将多个原子单元拼接为完整文本,比如 C In ("a", "b") 会被整体匹配 predicate = originalTextFor(OneOrMore(pred_atom)) # 构建逻辑表达式解析器 expr = infixNotation( predicate, [ (logical_op, 2, opAssoc.LEFT) ] )
运行效果
执行测试代码:
query = '(A LIKE "%.something.com" AND B = 4) OR (C In ("a", "b") AND D Contains "asdf")' print(expr.parseString(query).asList())
会得到预期的输出结构:
[[['A LIKE "%.something.com"', 'AND', 'B = 4'], 'OR', ['C In ("a", "b")', 'AND', 'D Contains "asdf"']]]
规则说明
- 单独匹配引号字符串,避免引号内出现的AND/OR、括号等字符干扰解析逻辑
- 通过递归规则匹配配对括号,保证谓词内部(比如IN子句)的括号会被完整包含在原子谓词中,不会被误判为逻辑分组符
- 只有顶层用来划分逻辑优先级的括号,才会被
infixNotation识别为分组边界,符合SQL条件表达式的语法规则
内容的提问来源于stack exchange,提问作者Guy Jacoby
相关产品推荐
相关产品推荐

