2009-12-09 6 views
5

J'utilise Elixir dans un projet qui se connecte à une base de données postgres. Je veux exécuter la requête suivante sur la base de données à laquelle je suis connecté, mais je ne suis pas sûr de savoir comment le faire car je suis plutôt nouveau à Elixir et SQLAlchemy. Quelqu'un sait comment?Exécuter une requête sql avec Elixir

VACUUM FULL ANALYZE table

Mise à jour

L'erreur est: "UnboundExecutionError: Impossible de trouver une liaison configurée sur l'expression SQL ou cette session". Et le même résultat avec session.close() émis avant. J'ai essayé de faire metadata.bind.execute() et cela a fonctionné pour une sélection simple. Mais pour le VACUUM il a dit - "InternalError: (InternalError) VACUUM ne peut pas courir à l'intérieur d'un bloc de transaction", alors maintenant j'essaie de comprendre comment désactiver cela.

Mise à jour 2

Je peux obtenir la requête à exécuter, mais je reçois toujours la même erreur - même lorsque je crée une nouvelle session et fermer le précédent.

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

et la sortie que je reçois est

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' {} 

Mise à jour 3

Merci à tous ceux qui ont répondu. Je n'étais pas capable de trouver la solution que je voulais, mais je pense que je vais juste aller avec celui décrit ici PostgreSQL - how to run VACUUM from code outside transaction block?. Ce n'est pas idéal, mais ça fonctionne.

Répondre

10

Zut. Je savais que la réponse allait être juste sous mon nez. En supposant que vous configurez votre connexion comme je l'ai fait.

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

La solution à c'était aussi simple que

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) 

Ceci est similaire à ce qui a été suggéré ici PostgreSQL - how to run VACUUM from code outside transaction block? parce que là-dessous, sqlalchemy utilise psycopg pour établir la connexion à Postgres. Connection.connection est un proxy de la connexion psycopg. Une fois que je me suis rendu compte de cela, ce problème est revenu à l'esprit et j'ai décidé d'en prendre un autre coup.

Espérons que cela aide quelqu'un.

0

Si vous avez accès à la session SQLAlchemy, vous pouvez exécuter des instructions SQL arbitraires via sa méthode execute:

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

J'ai essayé, mais j'ai obtenu un UnboundExecutionError. session est une instance de sqlalchemy.orm.scoping.ScopedSession et lorsque j'appelle session.commit() pour mes autres requêtes, cela fonctionne. Est-ce important si c'est avant ou après la validation? – mozillalives

+0

Vous pouvez essayer de faire session.close() avant d'exécuter l'instruction. En outre, l'erreur est venue avec traceback, qu'est-ce que cela dit? –

+0

"UnboundExecutionError: Impossible de localiser une liaison configurée sur l'expression SQL ou cette session". Et le même résultat avec session.close() émis avant. J'ai essayé de faire metadata.bind.execute() et cela a fonctionné pour une sélection simple. Mais pour le VACUUM il a dit - "InternalError: (InternalError) VACUUM ne peut pas courir à l'intérieur d'un bloc de transaction", alors maintenant j'essaie de comprendre comment désactiver cela. – mozillalives

0

(Selon la version Postgres) vous avez très probablement do not want courir "VACUUM FULL".

1

UnboundExecutionError indique que votre session n'est pas liée à un moteur et qu'il n'y a aucun moyen de découvrir le moteur de requête passé à execute(). Vous pouvez utiliser directement engine.execute() ou transmettre un paramètre supplémentaire mapper (mappeur ou modèle mappé correspondant à la table utilisée dans la requête) à session.execute() pour aider SQLAlchemy à découvrir le moteur approprié.

Le InternalError indique que vous essayez d'exécuter cette instruction à l'intérieur explicitement (avec l'instruction BEGIN) a commencé la transaction. Avez-vous publié quelques déclarations avant sans appeler commit()? Si oui, appelez simplement la méthode commit() ou rollback() pour fermer la transaction avant de faire VACUUM. Notez également qu'il existe plusieurs paramètres à sessionmaker() qui indiquent SQLAlchemy lorsque la transaction doit être démarrée.

+0

Ah, merci. J'ai essayé (voir mise à jour 2) mais il semble toujours commencer une transaction quelque part. Je pensais que c'était peut-être juste de réutiliser l'ancienne connexion, mais avec echo_pool = True la sortie indique qu'une nouvelle connexion est en cours. – mozillalives

2

Vous devez lier la session à un moteur

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