2009-09-08 25 views
38

Ich möchte eine SQL-Schnittstelle auf einem nicht relationalen Datenspeicher erstellen. Nicht relationaler Datenspeicher, aber es ist sinnvoll, relational auf die Daten zuzugreifen.SQL mit Python analysieren

Ich untersuche mit ANTLR einen AST, der die SQL als eine relationale Algebra Ausdruck darstellt. Dann geben Sie Daten zurück, indem Sie den Baum auswerten/gehen.

Ich habe noch nie einen Parser implementiert, und deshalb möchte ich einen Ratschlag, wie Sie am besten einen SQL-Parser und Evaluator implementieren.

  • Klingt der oben beschriebene Ansatz richtig?
  • Gibt es andere Tools/Bibliotheken, die ich untersuchen sollte? Wie PLY oder Pyparsing.
  • Zeiger auf Artikel, Bücher oder Quellcode, die mir helfen wird geschätzt.

Update:

implementiert ich einen einfachen SQL-Parser pyparsing verwenden. In Kombination mit Python-Code, der die relationalen Operationen für meinen Datenspeicher implementiert, war dies ziemlich einfach.

Wie ich in einem der Kommentare gesagt habe, war der Zweck der Übung, die Daten für die Berichts-Engines verfügbar zu machen. Um dies zu tun, muss ich wahrscheinlich einen ODBC-Treiber implementieren. Das ist wahrscheinlich eine Menge Arbeit.

+2

Warum SQL-Beschränkungen für Objekte auferlegen? Was ist zu gewinnen? Was ist falsch mit OQL? http://en.wikipedia.org/wiki/Object_Query_Language –

+7

Zu gewinnen: Eine Abfrage-Schnittstelle, die eine große Anzahl von Reporting-Tools verwenden kann. Ich plane, einen ODBC-Treiber auf dem Client zu implementieren. So können Geschäftsbenutzer Crystal Reports, Excel usw. zum Abrufen von Daten aus dem Datenspeicher verwenden. OQL, obwohl es wahrscheinlich eine nette Abfragesprache ist (ich habe es nie benutzt), ist nicht so weit verbreitet wie SQL. – codeape

+1

+1 beide: eines der größten Probleme mit OO-Datenbanken ist genau das Fehlen von Berichts-Engines :( – van

Antwort

33

Ich habe dieses Thema ziemlich ausführlich untersucht. Python-sqlparse ist ein nicht validierender Parser, der nicht wirklich benötigt wird. Die Beispiele in antlr brauchen viel Arbeit, um sie zu einem netten Ast in Python zu konvertieren. Die SQL-Standard-Grammer sind here, aber es wäre ein Vollzeit-Job, um sie selbst zu konvertieren, und es ist wahrscheinlich, dass Sie nur eine Teilmenge von ihnen benötigen würden, d. H. Keine Joins. Sie könnten versuchen, auch die gadfly (eine Python-SQL-Datenbank) zu betrachten, aber ich vermied es, da sie ihr eigenes Parsingtool verwendeten.

Für meinen Fall brauchte ich nur eine Where-Klausel. Ich versuchte booleneo (ein boolescher Ausdrucksparser), der mit pyparsing geschrieben wurde, aber endete, indem ich pyparsing von Grund auf verwendete. Der erste Link im Reddit-Post von Mark Ruschakoff gibt ein SQL-Beispiel, das es verwendet. Whoosh eine Volltext-Suchmaschine verwendet es auch, aber ich habe nicht auf die Quelle geschaut, um zu sehen, wie.

Pyparsing ist sehr einfach zu bedienen und Sie können sehr einfach anpassen, um nicht genau das gleiche wie SQL (die meisten der Syntax, die Sie nicht brauchen). Ich mochte nicht ply, da es einige Magie verwendet, die Namenskonventionen verwendet.

Kurz gesagt, es wird wahrscheinlich stark genug sein, um zu tun, was Sie brauchen, und die einfache Integration mit Python (mit einfachen Callbacks und Fehlerbehandlung) wird die Erfahrung ziemlich schmerzlos machen.

+1

Vielen Dank für Ihre Erfahrungen Anfangs, sehr begrenzte Tests von python-sqlparse, es scheint, dass ich in der Lage sein könnte, es zu verwenden.Ich werde versuchen, mit dem zurückgegebenen Wert von der '' parse''-Funktion in Python-sqlparse zu arbeiten. Aber ich werde in PyparSing schauen – codeape

+1

Pyparsing ist ein gutes Werkzeug dafür, mit vielen Beispielen für das Parsen von Sql. –

+2

Dieses Plakat auf dem Pjapssing Wiki (http://pyparsing.wikispaces.com/message/view/home/14105203) hat gerade den Abschluss gemeldet ein SQL-SELECT-Parser - vielleicht könnten Sie ihn/sie für Hilfe, Vorschläge oder sogar den Code kontaktieren – PaulMcG

9

This reddit post schlägt Python-sqlparse als eine vorhandene Implementierung, unter ein paar anderen Links.

+0

Vielen Dank für den Vorschlag. Python-sqlparse sieht interessant aus, ich werde es versuchen. – codeape

2

TwoLaid Python SQL Parser funktioniert sehr gut für meine Zwecke . Es ist in C geschrieben und muss kompiliert werden. Es ist robust.Es analysiert einzelne Elemente jeder Klausel.

https://github.com/TwoLaid/python-sqlparser

ich bin mit Abfragen Spaltennamen zu analysieren, in Report-Header zu verwenden. Hier ist ein Beispiel.

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']