2009-12-09 18 views
5

Sto utilizzando Elixir in un progetto che si collega a un database Postgres. Voglio eseguire la seguente query sul database a cui sono connesso, ma non sono sicuro di come farlo poiché sono piuttosto nuovo per Elixir e SQLAlchemy. Qualcuno sa come?Esegui query SQL con Elixir

VACUUM FULL ANALYZE table

Aggiornamento

L'errore è: "UnboundExecutionError: Impossibile trovare un vicolo cieco configurato sull'espressione SQL o questa sessione". E lo stesso risultato con session.close() emesso prima. Ho provato a fare metadata.bind.execute() e questo ha funzionato per una semplice selezione. Ma per il VACUUM ha detto: "InternalError: (InternalError) VACUUM non può essere eseguito all'interno di un blocco di transazione", quindi ora sto cercando di capire come disattivarlo.

Update 2

posso ottenere la query da eseguire, ma sto ancora ricevendo lo stesso errore - anche quando creo una nuova sessione e chiudere quello precedente.

from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 

# ... insert stuff 
old_session.commit() 
old_session.close() 

new_sess = sessionmaker(autocommit=True) 
new_sess.configure(bind=create_engine('postgres://user:[email protected]/db', echo=True)) 
sess = new_sess() 
sess.execute('VACUUM FULL ANALYZE table') 
sess.close() 

e l'uscita che ottengo è

2009-12-10 10:00:16,769 INFO sqlalchemy.engine.base.Engine.0x...05ac VACUUM FULL ANALYZE table 
2009-12-10 10:00:16,770 INFO sqlalchemy.engine.base.Engine.0x...05ac {} 
2009-12-10 10:00:16,770 INFO sqlalchemy.engine.base.Engine.0x...05ac ROLLBACK 
finishing failed run, (InternalError) VACUUM cannot run inside a transaction block 
'VACUUM FULL ANALYZE table' {} 

Update 3

Grazie a tutti coloro che hanno risposto. Non sono riuscito a trovare la soluzione che volevo, ma penso che andrò con quella descritta qui PostgreSQL - how to run VACUUM from code outside transaction block?. Non è l'ideale, ma funziona.

risposta

10

Dannazione. Sapevo che la risposta sarebbe stata proprio sotto il mio naso. Supponendo che tu abbia configurato la tua connessione come ho fatto io.

metadata.bind = 'postgres://user:[email protected]/db' 

La soluzione a questo è stato così semplice come

conn = metadata.bind.engine.connect() 

old_lvl = conn.connection.isolation_level 
conn.connection.set_isolation_level(0) 
conn.execute('vacuum analyze table') 
conn.connection.set_isolation_level(old_lvl) 

Questo è simile a quello che è stato suggerito qui PostgreSQL - how to run VACUUM from code outside transaction block? perché sotto sotto, SQLAlchemy utilizza psycopg per effettuare la connessione a Postgres. Connection.connection è un proxy per la connessione psycopg. Una volta capito questo, questo problema mi è tornato in mente e ho deciso di prenderne un'altra.

Speriamo che questo aiuti qualcuno.

0

Se si ha accesso alla sessione SQLAlchemy, è possibile eseguire istruzioni SQL arbitrarie attraverso il suo metodo execute:

session.execute("VACUUM FULL ANALYZE table") 
+0

Ho provato, ma ho ottenuto un UnboundExecutionError. session è un'istanza di sqlalchemy.orm.scoping.ScopedSession e quando chiamo session.commit() per le mie altre query, funziona. Importa se è prima o dopo il commit? – mozillalives

+0

Puoi provare a fare session.close() prima di eseguire l'istruzione. Inoltre, si spera che l'errore sia arrivato con traceback, cosa dice? –

+0

"UnboundExecutionError: impossibile trovare un binding configurato sull'espressione SQL o in questa sessione". E lo stesso risultato con session.close() emesso prima. Ho provato a fare metadata.bind.execute() e questo ha funzionato per una semplice selezione. Ma per il VACUUM ha detto: "InternalError: (InternalError) VACUUM non può essere eseguito all'interno di un blocco di transazione", quindi ora sto cercando di capire come disattivarlo. – mozillalives

0

(A seconda della versione Postgres) è più probabile do not want di eseguire "VUOTO FULL".

1

UnboundExecutionError indica che la sessione non è collegata a un motore e non è possibile scoprire il motore dalla query passata a execute(). È possibile utilizzare direttamente engine.execute() o passare il parametro mapper aggiuntivo (il mapper o il modello mappato corrispondente alla tabella utilizzata nella query) a session.execute() per consentire a SQLAlchemy di rilevare il motore corretto.

Il InternalError indica che si sta tentando di eseguire questa istruzione all'interno di una transazione avviata esplicitamente (con istruzione BEGIN). Avete già rilasciato alcune dichiarazioni senza chiamare lo commit()? In tal caso, è sufficiente chiamare il metodo commit() o rollback() per chiudere la transazione prima di eseguire VACUUM. Si noti inoltre che esistono diversi parametri su sessionmaker() che indicano a SQLAlchemy quando deve essere avviata la transazione.

+0

Ah, grazie. L'ho provato (vedi aggiornamento 2) ma sembra che stia iniziando una transazione da qualche parte. Ho pensato che forse stava solo riutilizzando la vecchia connessione, ma con echo_pool = True l'output indica che è in corso una nuova connessione. – mozillalives

2

hai bisogno di impegnare la sessione per un motore

session.bind = metadata.bind 
session.execute('YOUR SQL STATEMENT')