2017-11-27 3 views
0

Als ich select_parser.py from pyparsing nehmen, und führen Sie es mit pyparsing 2.2.0 mit diesem Code:Wie erhalten Sie Tabellennamen aus SQL mit select_parser.py aus pyparsing?

query="select z.a, b from test_table left join test2_table where 1=1 and b in (select bb from foo)" 
for key, val in select_stmt.parseString(query, parseAll=True).items(): 
    print "%s: %s" % (key, val) 

ich

$ python select_parser.pyparsing.py 
where_expr: [['1', '=', '1'], 'AND', ['b', 'IN', ['SELECT', [['bb']], 'FROM', 'foo']]] 
from: [['test_table', ['LEFT', 'JOIN'], 'test2_table', []]] 
columns: [['z.a'], ['b']] 

Obwohl ein benanntes Element "Tabelle" in der ursprünglichen Definition gibt es:

single_source = ((Group(database_name("database") + "." + table_name("table*")) | table_name("table*")) + 

Es gibt keinen Diktatschlüssel, der mit dem Namen "Tabelle" ausgegeben wird.

Vielleicht hat das "von" Element die Dinge zuerst konsumiert? Ich verstehe nicht die genaue Logik, wie die benannten Elemente gefüllt werden, und ich habe keine klare Idee vom Lesen der Dokumente (mehrere Gespräche, etc.) bekommen.

Wie kann ich select_parser.py verwenden, um alle Tabellennamen in einer SQL-Abfrage abzurufen?

Hinweis: Die richtige Antwort hier ist eine Liste (oder einen Satz): test_table, test2_table, foo.

Ich könnte durch "aus" und Graben-Listen gehen, aber das scheint hacky, ich weiß nicht, ob es funktionieren würde, und es scheint nicht, wie Pyparsing soll funktionieren.

Ich sehe this question, this one und this one, aber ich verstehe nicht, wie sie hier helfen.

Antwort

1

Der Beispielcode, mit dem Sie verbunden sind, enthält einen Anruf an runTests. Dies ist ein großartiges Werkzeug, um verschiedene Test-Strings zu testen und Komponententests für Ihren Parser zu schreiben.

Wenn Ihre Abfrage-String im Aufruf runTests Einfügen, bekommen wir diese Ausgabe:

select z.a, b from test_table left join test2_table where 1=1 and b in (select bb from foo) 
['SELECT', [['z.a'], ['b']], 'FROM', ['test_table', ['LEFT', 'JOIN'], 'test2_table', []], 'WHERE', [['1', '=', '1'], 'AND', ['b', 'IN', ['SELECT', [['bb']], 'FROM', 'foo']]]] 
- columns: [['z.a'], ['b']] 
    [0]: 
    ['z.a'] 
    [1]: 
    ['b'] 
- from: [['test_table', ['LEFT', 'JOIN'], 'test2_table', []]] 
    [0]: 
    ['test_table', ['LEFT', 'JOIN'], 'test2_table', []] 
    - table: [['test_table'], ['test2_table']] 
     [0]: 
     ['test_table'] 
     [1]: 
     ['test2_table'] 
- where_expr: [['1', '=', '1'], 'AND', ['b', 'IN', ['SELECT', [['bb']], 'FROM', 'foo']]] 
    [0]: 
    ['1', '=', '1'] 
    [1]: 
    AND 
    [2]: 
    ['b', 'IN', ['SELECT', [['bb']], 'FROM', 'foo']] 
    [0]: 
     b 
    [1]: 
     IN 
    [2]: 
     ['SELECT', [['bb']], 'FROM', 'foo'] 
     - columns: [['bb']] 
     [0]: 
      ['bb'] 
     - from: ['foo'] 
     - table: [['foo']] 
     [0]: 
      ['foo'] 

Die ‚table‘ Namen sind dort, aber Sie werden einige Navigation der Struktur zu tun haben, zu zu ihnen kommen. Hier ist eine Möglichkeit:

result = select_stmt.parseString(query) 
table_names = [] 
def visit_structure(struct): 
    if 'table' in struct: 
     table_names.extend(t[0] for t in struct.table) 
    for substruct in struct: 
     if isinstance(substruct, ParseResults): 
      visit_structure(substruct) 

visit_structure(result) 
print(table_names) 

Gibt:

['test_table', 'test2_table', 'foo'] 

Für zukünftige Auflistung Ihrer analysierten Daten, die Nutzung der ParserElement.runTests und ParseResults.dump Methoden.

+0

Danke! Ich sah runTests, und Dump, und ihre Ausgabe, aber 1) Ich wusste nicht über die struct.table-Format, 2) Ich kannte nicht das Paradigma für die Traversierung des Baumes. – dfrankow

+0

Benannte Ergebnisfelder können entweder mit 'result [" name "]' dict-key notation oder 'result.name' object-attribute Notation aufgerufen werden (außer dict notation wird KeyError auslösen, wenn der Name nicht existiert, während die Attributnotation zurückkehrt ''). Weitere Informationen finden Sie hier in der Online-Dokumentation: https://pythonhosted.org/pyparsing/pyparsing.ParseResults-class.html. Wie beim Durchqueren des Baumes wird hier nur der verschachtelte Parse-Datenbereich durchlaufen, der von & ldquor; parseString "zurückgegeben wird. Da Teilausdrücke in pyparierende 'Gruppen' eingeschlossen sind, erhalten Sie Unterstrukturen in Ihren analysierten Ergebnissen. – PaulMcG

Verwandte Themen