我想在非关系数据存储之上创建一个 SQL 接口。非关系数据存储,但以关系方式访问数据是有意义的。
我正在研究使用 ANTLR 生成将 SQL 表示为关系代数表达式的 AST。然后通过评估/遍历树返回数据。
我以前从未实现过解析器,因此我想要一些关于如何最好地实现 SQL 解析器和求值器的建议。
更新:
我使用 pyparsing 实现了一个简单的 SQL 解析器。结合针对我的数据存储实现关系操作的 Python 代码,这非常简单。
正如我在其中一条评论中所说,练习的目的是使数据可供报告引擎使用。为此,我可能需要实施 ODBC 驱动程序。这可能是很多工作。
我已经非常广泛地研究了这个问题。 Python-sqlparse 是一个非验证解析器,它并不是您真正需要的。 antlr 中的示例需要大量工作才能转换为 python 中的漂亮 ast。 sql 标准语法在here,但是自己转换它们将是一项全职工作,并且您可能只需要它们的一个子集,即没有连接。您也可以尝试查看 gadfly(一个 Python SQL 数据库),但我避免了它,因为他们使用了自己的解析工具。
就我而言,我基本上只需要一个 where 子句。我尝试了用 pyparsing 编写的 booleneo(一个布尔表达式解析器),但最终从头开始使用 pyparsing。 Mark Rushakoff 的 reddit 帖子中的第一个链接给出了一个使用它的 SQL 示例。 Whoosh 全文搜索引擎也使用它,但我没有查看源代码以了解如何使用它。
Pyparsing 非常易于使用,您可以非常轻松地将其自定义为与 SQL 不完全相同(您不需要的大部分语法)。我不喜欢 ply,因为它使用了一些使用命名约定的魔法。
简而言之,试试 pyparsing,它很可能足够强大,可以满足您的需求,并且与 python 的简单集成(具有简单的回调和错误处理)将使体验变得非常轻松。
这篇 reddit 帖子 建议将 python-sqlparse 作为现有的实现,以及其他几个链接。
TwoLaid 的 Python SQL 解析器非常适合我的目的。它是用 C 编写的,需要编译。它很坚固。它解析出每个子句的各个元素。
https://github.com/TwoLaid/python-sqlparser
我正在使用它来解析要在报告标题中使用的查询列名称。这是一个例子。
import sqlparser
def get_query_columns(sql):
'''Return a list of column headers from given sqls select clause'''
columns = []
parser = sqlparser.Parser()
# Parser does not like new lines
sql2 = sql.replace('\n', ' ')
# Check for syntax errors
if parser.check_syntax(sql2) != 0:
raise Exception('get_query_columns: SQL invalid.')
stmt = parser.get_statement(0)
root = stmt.get_root()
qcolumns = root.__dict__['resultColumnList']
for qcolumn in qcolumns.list:
if qcolumn.aliasClause:
alias = qcolumn.aliasClause.get_text()
columns.append(alias)
else:
name = qcolumn.get_text()
name = name.split('.')[-1] # remove table alias
columns.append(name)
return columns
sql = '''
SELECT
a.a,
replace(coalesce(a.b, 'x'), 'x', 'y') as jim,
a.bla as sally -- some comment
FROM
table_a as a
WHERE
c > 20
'''
print get_query_columns(sql)
# output: ['a', 'jim', 'sally']
当然,最好利用 python-sqlparse on Google Code
更新:现在我看到有人建议这样做——我同意这是值得的:
我正在使用
python-sqlparse
取得了巨大的成功。
在我的例子中,我正在处理已经验证过的查询,我的 AST-walking 代码可以对结构做出一些理智的假设。
SQLGlot 是一个无依赖的 SQL 解析器、转译器、优化器和引擎。突出显示语法错误。但是,应该注意 SQL 验证不是 SQLGlot 的目标,因此一些语法错误可能不会被注意到。 (基准)
sqltree 是 SQL 的实验性解析器,为 SQL 查询提供语法树。
sqloxide 将 sqlparser-rs 的 Rust 绑定包装到 python 包中。