python - La ejecución de múltiples declaraciones con Postgresql a través de SQLAlchemy no persiste los cambios
(2)
Debe usar
db.engine.execute(...).first()
si desea ejecutar todo y obtener solo la primera fila.
Esto no funciona: la actualización no tiene ningún efecto:
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)
Al cambiar las declaraciones, se realiza la actualización y se selecciona con éxito:
command = "update account_balance set balance=200 where id=1; select content from blog where slug = ''meow'';"
content = db.engine.scalar(command)
¿Por qué el primero no funciona? Funciona en Pgadmin. He habilitado la confirmación automática con Flask-Sqlalchemy.
Estoy haciendo un taller sobre inyección SQL, ¡así que no reescriba la solución!
La forma en que funciona la confirmación automática de SQLAlchemy es que inspecciona las declaraciones emitidas, tratando de detectar si los datos se modifican o no :
..., SQLAlchemy implementa su propia función de "autocompromiso" que funciona de manera completamente consistente en todos los backends. Esto se logra mediante la detección de declaraciones que representan operaciones de cambio de datos, es decir, INSERTAR, ACTUALIZAR, ELIMINAR, así como declaraciones de lenguaje de definición de datos (DDL) como CREATE TABLE, ALTER TABLE y luego emitir un COMMIT automáticamente si no hay ninguna transacción en curso . La detección se basa en la presencia de la opción de ejecución
autocommit=True
en la instrucción. Si la declaración es una declaración de solo texto y la bandera no está establecida, se usa una expresión regular para detectar INSERT, UPDATE, DELETE, así como una variedad de otros comandos para un backend particular
Dado que varios conjuntos de resultados no son compatibles con el nivel SQLAlchemy, en su primer ejemplo, la detección simplemente omite la emisión de un COMPROMISO porque la primera instrucción es un SELECCIONAR, mientras que en su segundo ejemplo es una ACTUALIZACIÓN. No se realiza ningún intento de detectar declaraciones de modificación de datos de varias declaraciones.
Si observa
PGExecutionContext.should_autocommit_text()
, verá que hace una
coincidencia de
AUTOCOMMIT_REGEXP
regulares con
AUTOCOMMIT_REGEXP
.
En otras palabras, solo coincide al comienzo del texto.