57

非リレーショナル データ ストア上に SQL インターフェイスを作成したいと考えています。非リレーショナル データ ストアですが、リレーショナルな方法でデータにアクセスすることは理にかなっています。

ANTLRを使用して、SQL を関係代数式として表す AST を生成することを検討しています。次に、ツリーを評価/ウォークしてデータを返します。

これまでパーサーを実装したことがないので、SQL パーサーとエバリュエーターを最適に実装する方法についてアドバイスをお願いします。

  • 上記のアプローチは正しいと思いますか?
  • 調べる必要がある他のツール/ライブラリはありますか? PLYPyparsing のように。
  • 私を助ける記事、本、またはソースコードへのポインタは大歓迎です。

アップデート:

pyparsing を使用して単純な SQL パーサーを実装しました。データ ストアに対するリレーショナル操作を実装する Python コードと組み合わせると、これは非常に簡単でした。

コメントの 1 つで述べたように、演習のポイントは、レポート エンジンがデータを利用できるようにすることでした。これを行うには、おそらく ODBC ドライバーを実装する必要があります。これはおそらく大変な作業です。

4

5 に答える 5

43

私はこの問題をかなり広範囲に調査しました。Python-sqlparseは非検証パーサーであり、実際には必要なものではありません。antlrの例は、Pythonで素敵なastに変換するために多くの作業を必要とします。SQL標準の文法はここにありますが、自分で変換するのはフルタイムの仕事であり、それらのサブセットのみ、つまり結合は必要ない可能性があります。gadfly (Python SQLデータベース)も試してみることができますが、独自の解析ツールを使用しているため、避けました。

私の場合、基本的に必要なのはwhere句だけです。pyparsingで記述されたbooleneo (ブール式パーサー)を試しましたが、最初からpyparsingを使用することになりました。Mark Rushakoffのreddit投稿の最初のリンクは、それを使用したSQLの例を示しています。全文検索エンジンもそれを使用していますが、その方法を確認するためにソースを調べていません。

構文解析は非常に使いやすく、SQLとまったく同じにならないように非常に簡単にカスタマイズできます(ほとんどの構文は必要ありません)。命名規則を使用して魔法を使用するため、プライは好きではありませんでした。

要するに、pyparsingを試してみると、必要なことを実行するのに十分強力である可能性が高く、Pythonとの単純な統合(簡単なコールバックとエラー処理)により、エクスペリエンスは非常に簡単になります。

于 2009-09-08T19:25:54.630 に答える
11

この reddit の投稿では、他のいくつかのリンクの中で、既存の実装としてpython-sqlparseを提案しています。

于 2009-09-08T16:44:31.927 に答える
5

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']
于 2017-04-25T19:03:01.477 に答える
1

もちろん、Google Code で python-sqlparseを活用するのが最善かもしれません

更新:これが提案されていることがわかりました-これは価値があることに同意します:

于 2011-02-01T18:55:08.663 に答える