57

我想在非关系数据存储之上创建一个 SQL 接口。非关系数据存储,但以关系方式访问数据是有意义的。

我正在研究使用ANTLR来生成将 SQL 表示为关系代数表达式的 AST。然后通过评估/遍历树返回数据。

我以前从未实现过解析器,因此我想要一些关于如何最好地实现 SQL 解析器和求值器的建议。

  • 上面描述的方法听起来对吗?
  • 还有其他我应该研究的工具/库吗?像PLYPyparsing
  • 对我有帮助的文章、书籍或源代码的指针表示赞赏。

更新:

我使用 pyparsing 实现了一个简单的 SQL 解析器。结合对我的数据存储实现关系操作的 Python 代码,这相当简单。

正如我在其中一条评论中所说,练习的重点是让数据可供报告引擎使用。为此,我可能需要实现一个 ODBC 驱动程序。这可能是很多工作。

4

5 回答 5

43

我已经非常广泛地研究了这个问题。Python-sqlparse 是一个非验证解析器,它并不是您真正需要的。antlr 中的示例需要大量工作才能在 python 中转换为漂亮的 ast。sql 标准语法在这里,但是自己转换它们将是一项全职工作,而且您可能只需要它们的一个子集,即不需要连接。您也可以尝试查看gadfly(一个 Python SQL 数据库),但我避免使用它,因为他们使用了自己的解析工具。

就我而言,我基本上只需要一个 where 子句。我尝试了用 pyparsing 编写的booleneo(一个布尔表达式解析器),但最终从头开始使用 pyparsing。Mark Rushakoff 的 reddit 帖子中的第一个链接给出了一个使用它的 SQL 示例。嗖嗖全文搜索引擎也使用它,但我还没有查看源代码以了解如何使用它。

Pyparsing 非常易于使用,您可以非常轻松地将其自定义为与 SQL 不完全相同(您不需要的大多数语法)。我不喜欢 ply,因为它使用命名约定使用了一些魔法。

简而言之,尝试一下 pyparsing,它很可能足够强大,可以满足您的需求,并且与 python 的简单集成(带有简单的回调和错误处理)将使体验非常轻松。

于 2009-09-08T19:25:54.630 回答
11

这篇 reddit 帖子建议将python-sqlparse作为现有实现,以及其他几个链接。

于 2009-09-08T16:44:31.927 回答
5

TwoLaid 的 Python SQL Parser 非常适合我的目的。它是用 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']
于 2017-04-25T19:03:01.477 回答
1

当然,最好在 Google Code 上利用 python-sqlparse

更新:现在我看到有人建议这样做 - 我同意这是值得的:

于 2011-02-01T18:55:08.663 回答
1

我使用python-sqlparse非常成功。

就我而言,我正在处理已经过验证的查询,我的 AST-walking 代码可以对结构做出一些合理的假设。

于 2021-06-08T19:25:19.900 回答