python - L'exécution de plusieurs instructions avec Postgresql via SQLAlchemy ne conserve pas les modifications.




(2)

Cela ne fonctionne pas - la mise à jour n'a aucun effet:

command = "select content from blog where slug = 'meow'; update account_balance set balance=200 where id=1; select 1 from blog;"
content = db.engine.scalar(command)

Changer les instructions effectue la mise à jour et sélectionne avec succès:

command = "update account_balance set balance=200 where id=1; select content from blog where slug = 'meow';"
content = db.engine.scalar(command)

Pourquoi le premier ne fonctionne pas? Cela fonctionne dans Pgadmin. J'ai activé autocommit avec Flask-Sqlalchemy.

Je suis en train de faire un atelier sur l'injection SQL, alors s'il vous plaît, ne réécrivez pas la solution!


Le fonctionnement automatique de SQLAlchemy consiste à inspecter les instructions émises afin de détecter si les données sont modifiées ou non :

..., SQLAlchemy implémente sa propre fonctionnalité "autocommit" qui fonctionne de manière totalement cohérente sur tous les backends. Ceci est réalisé en détectant les instructions représentant les opérations de changement de données, telles que les instructions INSERT, UPDATE, DELETE, ainsi que les instructions DDL (langage de définition de données) telles que CREATE TABLE, ALTER TABLE, puis en émettant automatiquement un COMMIT si aucune transaction n'est en cours. . La détection est basée sur la présence de l'option d'exécution autocommit=True sur l'instruction. Si l'instruction est une instruction textuelle et que l'indicateur n'est pas défini, une expression régulière est utilisée pour détecter INSERT, UPDATE, DELETE, ainsi que diverses autres commandes pour un backend particulier.

Étant donné que plusieurs ensembles de résultats ne sont pas pris en charge au niveau SQLAlchemy, dans votre premier exemple, la détection omet simplement d'émettre un COMMIT car la première instruction est un SELECT, où, comme dans le deuxième exemple, il s'agit d'un UPDATE. Aucune tentative de détection de données modifiant des instructions à partir de plusieurs instructions n'a lieu.

Si vous examinez PGExecutionContext.should_autocommit_text() , vous constaterez qu’il fait une correspondance regex avec AUTOCOMMIT_REGEXP . En d'autres termes, il ne correspond qu'au début du texte.


Vous devez utiliser db.engine.execute(...).first() si vous voulez tout exécuter et obtenir uniquement la première ligne.





sqlalchemy