用Python解析SQL

cod*_*ape 42 python sql parsing pyparsing

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

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

我之前从未实现过解析器,因此我想就如何最好地实现SQL解析器和求值程序提出一些建议.

  • 上述方法听起来不错吗?
  • 我应该研究其他工具/库吗?像PLYPyparsing.
  • 指向可以帮助我的文章,书籍或源代码的指标表示赞赏.

更新:

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

正如我在其中一条评论中所说,演习的重点是将数据提供给报告引擎.为此,我可能需要实现ODBC驱动程序.这可能是很多工作.

Dav*_*ick 37

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

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

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

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

  • 在pyparsing wiki上的这张海报(http://pyparsing.wikispaces.com/message/view/home/14105203)刚刚报告完成了一个SQL SELECT解析器 - 也许你可以联系他/她寻求帮助,建议,甚至是代码. (2认同)
  • 我用pyparsing实现了它.Pyparsing对此非常有用. (2认同)

Mar*_*off 10

这篇reddit帖子暗示Python-sqlparse是一个现有的实现,在其他几个链接中.


dli*_*ink 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']
Run Code Online (Sandbox Code Playgroud)