2009-12-09 6 views
5

Ich verwende Elixir in einem Projekt, das eine Verbindung zu einer Postgres-Datenbank herstellt. Ich möchte die folgende Abfrage für die Datenbank ausführen, mit der ich verbunden bin, aber ich weiß nicht, wie ich das machen soll, da ich für Elixir und SQLAlchemy ziemlich neu bin. Wer weiß wie?SQL-Abfrage mit Elixir ausführen

VACUUM FULL ANALYZE table

aktualisieren

Der Fehler ist: "UnboundExecutionError: Es konnte keine bind konfiguriert SQL-Expression oder diese Sitzung lokalisieren". Und das gleiche Ergebnis mit session.close() zuvor ausgegeben. Ich habe versucht, metadata.bind.execute() und das für eine einfache Auswahl funktioniert. Aber für die VACUUM hieß es - "InternalError: (InternalError) VACUUM kann nicht innerhalb eines Transaktionsblocks laufen", also versuche ich jetzt herauszufinden, wie ich das ausschalten kann.

Update 2

ich die Abfrage bekommen kann ausführen, aber ich bin immer noch die gleichen Fehler - auch wenn ich eine neue Sitzung erstellt und die vorherigen schließen.

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() 

und die Ausgabe ich erhalte, ist

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

Vielen Dank an alle, die geantwortet haben. Ich war nicht in der Lage, die Lösung zu finden, die ich wollte, aber ich denke, ich gehe nur mit dem hier beschriebenen PostgreSQL - how to run VACUUM from code outside transaction block?. Es ist nicht ideal, aber es funktioniert.

Antwort

10

Dammit. Ich wusste, dass die Antwort direkt vor meiner Nase sein würde. Angenommen, Sie richten Ihre Verbindung so ein wie ich.

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

Die Lösung hierfür war so einfach wie

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) 

Dies ähnlich ist, was hier PostgreSQL - how to run VACUUM from code outside transaction block? weil unter vorgeschlagen wurde allen, sqlalchemy psycopg verwendet die Verbindung zu Postgres zu machen. Connection.connection ist ein Proxy für die psycopg-Verbindung. Als mir das klar wurde, kam mir dieses Problem wieder in den Sinn und ich beschloss, einen weiteren Schlag zu machen.

Hoffentlich hilft das jemand.

0

Wenn Sie Zugriff auf SQLAlchemy Sitzung haben, können Sie beliebige SQL-Anweisungen über seine execute Methode ausführen:

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

Ich habe das versucht, aber ich habe einen UnboundExecutionError. Sitzung ist eine Instanz von sqlalchemy.orm.scoping.ScopedSession und wenn ich session.commit() für meine anderen Abfragen aufrufen, funktioniert das. Ist es wichtig, ob es vor oder nach dem Commit ist? – mozillalives

+0

Sie können versuchen, session.close() auszuführen, bevor Sie die Anweisung ausführen. Außerdem kam der Fehler hoffentlich mit Traceback, was sagt das? –

+0

"UnboundExecutionError: Konnte eine Bindung nicht finden, die für den SQL-Ausdruck oder diese Sitzung konfiguriert wurde". Und das gleiche Ergebnis mit session.close() zuvor ausgegeben. Ich habe versucht, metadata.bind.execute() und das für eine einfache Auswahl funktioniert. Aber für die VACUUM hieß es - "InternalError: (InternalError) VACUUM kann nicht innerhalb eines Transaktionsblocks laufen", also versuche ich jetzt herauszufinden, wie ich das ausschalten kann. – mozillalives

0

(Abhängig von der Postgres-Version) Sie höchstwahrscheinlich do not want laufen "VACUUM FULL".

1

UnboundExecutionError besagt, dass Ihre Sitzung nicht an eine Engine gebunden ist und es keine Möglichkeit gibt, die Engine aus der Abfrage zu ermitteln, die an übergeben wurde. Sie können entweder engine.execute() direkt verwenden oder den zusätzlichen mapper-Parameter (entweder Mapper oder zugeordnetes Modell, der der in der Abfrage verwendeten Tabelle entspricht) an session.execute() übergeben, damit SQLAlchemy die richtige Engine erkennt.

Die InternalError besagt, dass Sie versuchen, diese Anweisung innerhalb explizit (mit BEGIN-Anweisung) gestarteter Transaktion auszuführen. Haben Sie schon einige Anweisungen davor ausgegeben, ohne commit() anzurufen? Wenn ja, rufen Sie einfach die Methode commit() oder rollback() auf, um die Transaktion zu schließen, bevor Sie VACUUM ausführen. Beachten Sie auch, dass es mehrere Parameter zu sessionmaker() gibt, die SQLAlchemy mitteilen, wann die Transaktion gestartet werden soll.

+0

Ah, danke. Ich habe es versucht (siehe Update 2), aber es scheint irgendwo noch eine Transaktion zu beginnen. Ich dachte, dass es vielleicht nur die alte Verbindung wiederverwendete, aber mit echo_pool = True zeigt die Ausgabe an, dass eine neue Verbindung hergestellt wird. – mozillalives

2

Sie müssen die Sitzung zu einem Motor binden

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