164 votes

Comment obtenir une requête SQL brute et compilée à partir d'une expression SQLAlchemy ?

J'ai un objet de requête SQLAlchemy et je veux obtenir le texte de la requête SQL compilée, avec tous ses paramètres liés (par exemple, pas de %s ou d'autres variables attendant d'être liées par le compilateur d'instructions ou le moteur de dialecte MySQLdb, etc).

Appel str() sur la requête révèle quelque chose comme ceci :

SELECT id WHERE date_added <= %s AND date_added >= %s ORDER BY count DESC

J'ai essayé de regarder dans query._params mais c'est un dict vide. J'ai écrit mon propre compilateur en utilisant cet exemple de la sqlalchemy.ext.compiler.compiles décorateur mais même la déclaration qui s'y trouve a encore %s où je souhaite obtenir des données.

Je n'arrive pas à comprendre quand mes paramètres sont mélangés pour créer la requête ; lorsque j'examine l'objet requête, ils sont toujours un dictionnaire vide (bien que la requête s'exécute correctement et que le moteur l'imprime lorsque vous activez la journalisation de l'écho).

Je commence à comprendre que SQLAlchemy ne veut pas que je connaisse la requête sous-jacente, car cela rompt la nature générale de l'interface de l'API d'expression avec toutes les différentes API de base de données. Je me fiche que la requête soit exécutée avant que je ne sache ce qu'elle était ; je veux juste savoir !

2voto

Rômulo Collopy Points 21

J'ai créé cette petite fonction que j'importe lorsque je veux imprimer la requête complète, étant donné que je suis au milieu d'un test lorsque le dialecte est déjà lié :

import re

def print_query(query):
    regex = re.compile(":(?P<name>\w+)")
    params = query.statement.compile().params
    sql = regex.sub("'{\g<name>}'", str(query.statement)).format(**params)
    print(f"\nPrinting SQLAlchemy query:\n\n")
    print(sql)
    return sql

0voto

user2757902 Points 473

Je pense qu'une déclaration pourrait faire l'affaire : http://docs.sqlalchemy.org/en/latest/orm/query.html?highlight=query

>>> local_session.query(sqlalchemy_declarative.SomeTable.text).statement
<sqlalchemy.sql.annotation.AnnotatedSelect at 0x6c75a20; AnnotatedSelectobject>
>>> x=local_session.query(sqlalchemy_declarative.SomeTable.text).statement
>>> print(x)
SELECT sometable.text 
FROM sometable

-1voto

Si vous utilisez PyMySQL avec SQLAlchemy, vous pouvez faire une astuce.

J'étais pressé et j'ai perdu beaucoup de temps, j'ai donc changé le pilote pour imprimer la déclaration courante avec des paramètres.

SQLAlchemy ne prend volontairement pas en charge l'enchaînement complet des valeurs littérales.

Mais PyMySQL a la méthode 'mogrify' qui le fait, mais SQLALchemy n'a pas de HOOK pour l'appeler en utilisant ORM insert/update (quand il contrôle le curseur) comme db.add ou commit/flush (pour la mise à jour).

Il suffit donc d'aller là où le conducteur utilise (pour savoir où utiliser) : pip show pycharm

Dans le dossier, trouvez et éditez le fichier cursors.py.

Dans la méthode :

def execute(self, query, args=None):

Sous la ligne :

query = self.mogrify(query, args)

Il suffit d'ajouter :

print(query)

Cela fonctionnera comme un charme, déboguera, résoudra le problème et supprimera l'impression.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X