我有以下示例 SQL(它变得更复杂):
select
*
from
(select
a,
b
from
agents)
我想使用sqlfluff解析这样的字符串
from sqlfluff.core import Parser
p = Parser(dialect='ansi')
parsed = p.parse_string(query)
并将查询分成两部分(最好分成两棵树/ParsedString),外部的和内部的。内部查询应插入到 CTAS 语句中,外部查询应引用它。
预期的伪代码:
outer_tree.set_innermost_token('reagents')
inner_tree.set_outermost_tokens('create or replace reagents as')
print(outer_tree.generate_SQL())
# !!! for simplicity I am removing the indentation
# select * from reagents
print(inner_tree.generate_SQL())
# !!! for simplicity I am removing the indentation
# create or replace reagents as select a, b from agents
请记住,这只是一个简单的示例,我知道基本的正则表达式在这种情况下可以有所帮助,但是,我的目标是修改更复杂的查询。另外,SQL 查询已经写好了,因此我不能只写一个生成器。
谢谢指点!
我查看了 cli.py 以及 Linter 的内部结构,但我只能生成与提供的相同的 SQL 代码(通过将第 222 行上的变量
filtered_source_patches
设置为 None
) .
Parser
类获取解析的结构,但您可能会发现
parse_string()
类上的
Linter
方法更有用。获得解析后的对象后,您可以使用
recursive_crawl
来查找特定类型的段。在下面的示例中,我们搜索
select_statement
段,您可以看到我们找到了两个(一个嵌套在另一个内)。
from sqlfluff.core import Linter
# Whitespace removed for brevity
input_sql = "select * from (select a, b from agents)"
parsed = Linter(dialect="ansi").parse_string(input_sql)
print("File:", parsed.tree.raw)
# File: select * from (select a, b from agents)
for idx, outer_select in enumerate(parsed.tree.recursive_crawl("select_statement")):
print("Inner:", idx, outer_select.raw)
# Inner: 0 select * from (select a, b from agents)
# Inner: 1 select a, b from agents
听起来您想从内部生成一个 CREATE TABLE
语句,您可以通过简单的字符串操作来完成。替换外部 SQL 中的内容有点困难,但是您可以利用上面
pos_marker
变量的
outer_segment
属性中存储的位置信息来找出外部文件中的where 进行一些字符串操作.