A questão aqui é como o sqlalchemy decide emitir um commit após cada instrução.
se um texto for passado para
engine.execute
, o sqlalchemy tentará determinar se o texto é um DML ou DDL usando o seguinte regex. Você pode encontrá-lo nas fontes aqui AUTOCOMMIT_REGEXP = re.compile(
r"\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER)", re.I | re.UNICODE
)
Isso só detecta as palavras se estiverem no início do texto, ignorando quaisquer espaços em branco à esquerda. Então, enquanto sua primeira tentativa
# works fine
, o segundo exemplo não reconhece que um commit precisa ser emitido após a instrução ser executada porque a primeira palavra é SET
. Em vez disso, sqlalchemy emite um rollback, então
# appears to succeed/does NOT throw any error
. a solução mais simples é confirmar manualmente.
exemplo:
engine.execute("SET ROLE read_write; CREATE table testpublic (id int, val text); COMMIT;")
ou, envolva o sql em
text
e defina autocommit=True
, como mostrado na documentação stmt = text('set role read_write; create table testpublic (id int, val text);').execution_options(autocommit=True)
e.execute(stmt)