是否存在SQLFluff函数可将解析后的查询字典还原为SQL字符串?
如何将SQLFluff解析后的字典重构为SQL查询字符串
SQLFluff官方确实没有提供直接将.parse()返回的字典转回SQL的API,但可以通过以下两种方式实现需求:
方法1:利用SQLFluff内部AST序列化逻辑
SQLFluff的解析字典对应其内部的抽象语法树(AST)节点结构,我们可以通过构建对应的AST节点对象,调用其序列化方法生成SQL:
import sqlfluff from sqlfluff.core.parser.segments import RawSegment, BaseSegment def dict_to_sql(ast_dict, dialect="postgres"): dialect_obj = sqlfluff.get_dialect(dialect) def build_segment(node): if isinstance(node, list): return [build_segment(item) for item in node] if isinstance(node, dict): if len(node) == 1: seg_type, content = next(iter(node.items())) # 处理基础文本节点 if seg_type in ["keyword", "whitespace", "comma", "dot", "star", "raw_comparison_operator", "start_bracket", "end_bracket"]: return RawSegment(content, dialect=dialect_obj) # 匹配复合节点类 for cls in BaseSegment.__subclasses__(): if cls.__name__.lower() == seg_type: return cls(children=build_segment(content), dialect=dialect_obj) # 兜底处理未知节点 return BaseSegment(children=build_segment(content), dialect=dialect_obj) return node root_segment = build_segment(ast_dict["file"]["statement"]) return root_segment.serialized # 测试示例 parsed_result = sqlfluff.parse( """with cte1 as (select colA from table1), cte2 as (select colB from table2 inner join table1 on table2.colB = table1.colA) select * from cte2""", "postgres" ) print(dict_to_sql(parsed_result))
方法2:递归遍历字典拼接SQL
直接递归遍历解析字典的键值对,提取文本内容拼接成SQL,这种方式更轻量但需要覆盖所有可能的节点类型:
def reconstruct_sql(ast_node): sql_parts = [] if isinstance(ast_node, list): for item in ast_node: sql_parts.append(reconstruct_sql(item)) elif isinstance(ast_node, dict): for key, value in ast_node.items(): # 提取直接存储文本的节点 if key in ["keyword", "whitespace", "comma", "dot", "star", "raw_comparison_operator", "start_bracket", "end_bracket", "naked_identifier"]: sql_parts.append(str(value)) else: sql_parts.append(reconstruct_sql(value)) return "".join(sql_parts) # 测试示例 parsed_result = sqlfluff.parse( """with cte1 as (select colA from table1), cte2 as (select colB from table2 inner join table1 on table2.colB = table1.colA) select * from cte2""", "postgres" ) print(reconstruct_sql(parsed_result["file"]["statement"]))
注意事项
- 复杂SQL(如子查询、窗口函数、注释、特殊语法)需要补充对应节点的处理逻辑,两种方法才能完整生成原始SQL。
- 方法1依赖SQLFluff内部类结构,版本更新后可能需要适配;方法2更稳定,但需要手动维护节点类型与文本的映射关系。
内容的提问来源于stack exchange,提问作者Eric Mendes
相关产品推荐
相关产品推荐

