2009-09-08 14 views
38

Voglio creare un'interfaccia SQL su un archivio dati non relazionale. Archivio dati non relazionali, ma ha senso accedere ai dati in modo relazionale.Analisi SQL con Python

Sto cercando di utilizzare ANTLR per produrre un AST che rappresenta l'SQL come espressione di algebra relazionale. Quindi restituisci i dati valutando/camminando sull'albero.

Non ho mai implementato un parser in precedenza e vorrei quindi qualche consiglio su come implementare al meglio un parser e un analizzatore SQL.

  • L'approccio sopra descritto suona giusto?
  • Ci sono altri strumenti/librerie che dovrei esaminare? Come PLY o Pyparsing.
  • Puntatori ad articoli, libri o codice sorgente che mi aiuteranno sono apprezzati.

Aggiornamento:

ho implementato un semplice parser SQL utilizzando pyparsing. Combinato con il codice Python che implementa le operazioni relazionali contro il mio archivio dati, questo era abbastanza semplice.

Come ho detto in uno dei commenti, il punto dell'esercizio era rendere i dati disponibili ai motori di segnalazione. Per fare questo, probabilmente dovrò implementare un driver ODBC. Questo probabilmente è un sacco di lavoro.

+2

Perché imporre limitazioni SQL sugli oggetti? Cosa si può guadagnare? Cosa c'è di sbagliato in OQL? http://en.wikipedia.org/wiki/Object_Query_Language –

+7

Da acquisire: un'interfaccia di query che può essere utilizzata da un numero enorme di strumenti di reporting. Ho intenzione di implementare un driver ODBC sul client. In modo che gli utenti aziendali possano utilizzare Crystal Reports, Excel ecc. Per recuperare i dati dall'archivio dati. OQL, anche se probabilmente un bel linguaggio di query (non l'ho mai usato), non è così diffuso come SQL. – codeape

+1

+1: uno dei maggiori problemi con i database OO è proprio la mancanza di motori di segnalazione :( – van

risposta

33

Ho esaminato la questione in modo approfondito. Python-sqlparse è un parser non validante che non è proprio quello di cui hai bisogno. Gli esempi in antlr hanno bisogno di molto lavoro per convertirsi in un bello ast in python. Le grammatiche standard sql sono here, ma sarebbe un lavoro a tempo pieno per convertirle da soli ed è probabile che sia necessario solo un sottoinsieme di esse senza join. Potresti provare a guardare allo gadfly (un database sql python), ma l'ho evitato poiché usavano il loro strumento di analisi.

Per il mio caso, ho solo bisogno essenzialmente di una clausola where. Ho provato booleneo (un parser di espressioni booleane) scritto con pyparsing ma ho finito per usare pyparsing da zero. Il primo collegamento nel post reddit di Mark Rushakoff fornisce un esempio SQL che lo utilizza. Whoosh anche un motore di ricerca full text lo usa ma non ho guardato la fonte per vedere come.

Pyparsing è molto facile da usare e puoi facilmente personalizzarlo per non essere esattamente uguale a sql (la maggior parte della sintassi non ti servirà). Non mi piaceva la piega in quanto utilizza un po 'di magia usando le convenzioni di denominazione.

In breve dare una prova di pyparsing, sarà probabilmente abbastanza potente da fare ciò che ti serve e la semplice integrazione con python (con facili callback e gestione degli errori) renderà l'esperienza abbastanza indolore.

+1

Grazie per aver condiviso le tue esperienze. test iniziale, molto limitato su python-sqlparse, sembra che potrei essere in grado di usarlo, proverò a lavorare con il valore restituito dalla funzione '' parse'' in python-sqlparse, ma cercherò il pyparsing in In ogni caso – codeape

+1

Pyparsing è un ottimo strumento per questo, con molti esempi di parsing sql in giro. –

+2

Questo poster sul wiki di pyparsing (http://pyparsing.wikispaces.com/message/view/home/14105203) ha appena riportato di aver completato un parser SQL SELECT - forse potresti contattarlo per aiuto, suggerimenti o anche il codice – PaulMcG

9

This reddit post suggerisce Python-sqlparse come un'implementazione esistente, tra un paio di altri collegamenti.

+0

Grazie per il suggerimento Python-sqlparse sembra interessante, ci proveremo – codeape

2

di TwoLaid Python SQL Parser funziona molto bene per i miei scopi . È scritto in C e deve essere compilato. È robustoAnalizza i singoli elementi di ciascuna clausola.

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

sto usando per analizzare le query nomi delle colonne da utilizzare nelle intestazioni dei report. Ecco un esempio.

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