2009-12-09 12 views
5

Używam Elixir w projekcie, który łączy się z bazą danych PostgreSQL. Chcę uruchomić następujące zapytanie w bazie danych, z którą jestem połączony, ale nie jestem pewien, jak to zrobić, ponieważ jestem raczej nowym użytkownikiem Elixir i SQLAlchemy. Ktoś wie jak?Wykonaj kwerendę sql z Elixir

VACUUM FULL ANALYZE table

Aktualizacja

Błąd brzmi: "UnboundExecutionError: Nie można zlokalizować wiążą skonfigurowany na wyrażeniu SQL lub tej sesji". I ten sam wynik z session.close() wydany wcześniej. Spróbowałem zrobić metadata.bind.execute() i to działało dla prostego wyboru. Ale dla VACUUM powiedział - "InternalError: (InternalError) VACUUM nie może działać w bloku transakcji", więc teraz próbuję dowiedzieć się, jak to wyłączyć.

Aktualizacja 2

mogę zapytanie do wykonania, ale ja wciąż otrzymuję ten sam błąd - nawet gdy tworzę nową sesję i zamknąć poprzedni.

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

a wyjście mogę to

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

Dziękujemy wszystkim, którzy odpowiedzieli. Nie mogłem znaleźć rozwiązania, które chciałem, ale myślę, że pójdę z tym opisanym tutaj PostgreSQL - how to run VACUUM from code outside transaction block?. To nie jest idealne, ale działa.

Odpowiedz

10

cholery. Wiedziałem, że odpowiedź będzie pod moim nosem. Zakładając, że skonfigurowałeś swoje połączenie tak, jak ja.

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

Rozwiązaniem tego problemu było tak proste, jak

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) 

Jest to podobne do tego, co sugeruje tutaj PostgreSQL - how to run VACUUM from code outside transaction block? bo pod tym wszystkim, sqlalchemy wykorzystuje psycopg do nawiązania połączenia do PostgreSQL. Connection.connection to proxy połączenia z psycopg. Kiedy zdałem sobie z tego sprawę, ten problem powrócił i postanowiłem zrobić kolejny raz.

Mam nadzieję, że to pomoże komuś.

0

Jeśli masz dostęp do sesji sqlalchemy można wykonać dowolne polecenia SQL za pośrednictwem metody execute:

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

Próbowałem, ale dostałem UnboundExecutionError. session jest instancją sqlalchemy.orm.scoping.ScopedSession i kiedy wywołuję session.commit() dla innych moich zapytań, to działa. Czy to ma znaczenie, czy to przed, czy po zatwierdzeniu? – mozillalives

+0

Możesz spróbować zrobić session.close() przed wykonaniem instrukcji. Ponadto, błąd miejmy nadzieję przyszedł z traceback, co to mówi? –

+0

"UnboundExecutionError: Nie można znaleźć powiązania skonfigurowanego w wyrażeniu SQL lub tej sesji". I ten sam wynik z session.close() wydany wcześniej. Spróbowałem zrobić metadata.bind.execute() i to działało dla prostego wyboru. Ale dla VACUUM powiedział - "InternalError: (InternalError) VACUUM nie może działać w bloku transakcji", więc teraz próbuję dowiedzieć się, jak to wyłączyć. – mozillalives

0

(w zależności od wersji PostgreSQL) najprawdopodobniej do not want uruchomić „próżniowe Pełny”.

1

UnboundExecutionError mówi, że twoja sesja nie jest związana z silnikiem i nie ma możliwości odkrycia silnika z zapytania przesłanego do execute(). Możesz bezpośrednio użyć engine.execute() lub przekazać dodatkowy parametr mapper (program odwzorowujący lub zmapowany model odpowiadający tabeli użytej w zapytaniu) do session.execute(), aby pomóc SQLAlchemy w wykryciu właściwego silnika.

InternalError mówi, że próbujesz wykonać tę instrukcję wewnątrz jawnie (z instrukcją BEGIN) rozpoczętej transakcji Czy wydałeś kilka oświadczeń przed tym, dzwoniąc pod numer commit()? Jeśli tak, po prostu wywołaj metodę commit() lub rollback(), aby zamknąć transakcję przed wykonaniem VACUUM. Zauważ też, że istnieje kilka parametrów do sessionmaker(), które informują SQLAlchemy, kiedy należy rozpocząć transakcję.

+0

Ah, dzięki. Próbowałem tego (patrz aktualizacja 2), ale nadal wydaje się, że gdzieś rozpoczyna się transakcja. Pomyślałem, że może to było ponowne użycie starego połączenia, ale z echo_pool = True wynik wskazuje, że jest tworzone nowe połączenie. – mozillalives

2

Trzeba powiązać sesję do silnika

session.bind = metadata.bind 
session.execute('YOUR SQL STATEMENT') 
Powiązane problemy