You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Python __select__方法的process_sql_query添加括号支持?

扩展process_sql_query函数支持带括号的WHERE子句条件分组

要支持带括号的条件分组,核心是处理逻辑运算的优先级与嵌套分组,最直观的实现方式是用栈结构维护嵌套的条件上下文,同时兼顾AND/OR的默认优先级(AND高于OR)。以下是具体实现思路和代码:

实现步骤

1. 预处理:将WHERE子句拆分为标记流(Tokens)

先把原始WHERE字符串拆分为可解析的标记,包括括号、逻辑运算符(AND/OR)、单个条件片段。拆分时要保留括号完整性,同时忽略多余空格,还要兼容带引号的条件(比如status = 'active')。

2. 栈结构处理嵌套分组

用栈存储当前的条件上下文,每个上下文包含两个元素:

  • 当前组的条件列表
  • 当前组的逻辑运算符(用于合并条件)
    遇到左括号时压入当前上下文,开启新的子组;遇到右括号时弹出栈顶,将子组的结果合并到上层上下文。

3. 处理AND/OR优先级

默认AND优先级高于OR,因此遇到OR时,需要先将当前已有的AND组合条件合并为一个整体,再加入OR的逻辑分支。

完整代码实现

def evaluate_condition(row, condition):
    # 单个条件的判断逻辑示例(生产环境建议用ast解析替代eval)
    return eval(condition, {}, row)

def tokenize_where_clause(where_clause):
    # 拆分WHERE子句为标记流,兼容带引号的条件
    tokens = []
    current_token = []
    in_quotes = False
    for char in where_clause:
        if char in ('"', "'"):
            in_quotes = not in_quotes
            current_token.append(char)
        elif not in_quotes and char in '()':
            if current_token:
                tokens.append(''.join(current_token).strip())
                current_token = []
            tokens.append(char)
        elif not in_quotes and char.isspace():
            if current_token:
                tokens.append(''.join(current_token).strip())
                current_token = []
        else:
            current_token.append(char)
    if current_token:
        tokens.append(''.join(current_token).strip())
    return [t for t in tokens if t]

def process_sql_query(where_clause, data):
    if not where_clause:
        return data
    
    tokens = tokenize_where_clause(where_clause)
    # 栈元素:(条件列表, 当前逻辑运算符),初始上下文用OR作为默认(不影响单个条件)
    stack = [([], 'OR')]
    current_conditions, current_op = stack[-1]
    
    i = 0
    while i < len(tokens):
        token = tokens[i]
        if token == '(':
            # 压入当前上下文,开启新子组
            stack.append(([], 'OR'))
            current_conditions, current_op = stack[-1]
            i += 1
        elif token == ')':
            # 弹出子组,合并到上层上下文
            stack.pop()
            if not stack:
                raise SyntaxError("WHERE子句括号不匹配")
            parent_conditions, parent_op = stack[-1]
            # 将子组条件封装为可调用的判断函数
            def sub_group_check(row, conds=current_conditions, op=current_op):
                if op == 'AND':
                    return all(evaluate_condition(row, cond) for cond in conds)
                else:
                    return any(evaluate_condition(row, cond) for cond in conds)
            parent_conditions.append(sub_group_check)
            current_conditions, current_op = parent_conditions, parent_op
            i += 1
        elif token in ('AND', 'OR'):
            # 更新当前上下文的逻辑运算符
            current_op = token
            stack[-1] = (current_conditions, current_op)
            i += 1
        else:
            # 普通条件加入当前上下文
            current_conditions.append(token)
            i += 1
    
    if len(stack) != 1:
        raise SyntaxError("WHERE子句括号不匹配")
    
    # 最终条件判断逻辑
    final_conditions, final_op = stack[0]
    def final_check(row):
        if final_op == 'AND':
            for cond in final_conditions:
                if callable(cond):
                    if not cond(row):
                        return False
                else:
                    if not evaluate_condition(row, cond):
                        return False
            return True
        else:
            for cond in final_conditions:
                if callable(cond):
                    if cond(row):
                        return True
                else:
                    if evaluate_condition(row, cond):
                        return True
            return False
    
    # 过滤数据
    return [row for row in data if final_check(row)]

代码关键点说明

  1. tokenize_where_clause:处理带引号的条件,避免把引号内的空格或括号误拆分,确保标记流的正确性。
  2. 栈上下文管理:每个括号组对应一个栈元素,嵌套分组时通过压栈/弹栈切换上下文,保证括号内的条件被独立处理。
  3. 嵌套条件合并:将括号内的子条件转换为可调用的判断函数,上层上下文直接调用该函数即可完成分组判断。
  4. 优先级处理:同一上下文内的AND条件会被先合并为连续的all()判断,OR则作为分支用any()判断,符合AND优先级高于OR的规则。

使用示例

# 测试数据
sample_data = [
    {'age': 35, 'status': 'active', 'salary': 60000, 'department': 'tech'},
    {'age': 28, 'status': 'inactive', 'salary': 45000, 'department': 'admin'},
    {'age': 40, 'status': 'active', 'salary': 55000, 'department': 'sales'},
]

# 带括号的WHERE子句
where_clause = "(age > 30 AND status = 'active') OR (salary > 50000 AND department = 'tech')"

# 处理查询
result = process_sql_query(where_clause, sample_data)
print(result)
# 输出:[{'age': 35, 'status': 'active', 'salary': 60000, 'department': 'tech'}, {'age': 40, 'status': 'active', 'salary': 55000, 'department': 'sales'}]

内容的提问来源于stack exchange,提问作者Celer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:52:51