Reputation: 816
For some reason engine connection commits automatically, which is not desired. I want to commit explicitly. Here's my code (it repeats official tutorial verbatim):
from sqlalchemy import Table, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from sqlalchemy.orm import registry
from sqlalchemy import create_engine
from sqlalchemy import ForeignKey
engine = create_engine('postgresql+psycopg2://user:password@localhost:5432/test_db', echo=True)
mapper_registry = registry()
Base = mapper_registry.generate_base()
user_table = Table(
"user_account",
mapper_registry.metadata,
Column("id", Integer, primary_key=True),
Column("name", String(30)),
Column("fullname", String),
)
mapper_registry.metadata.create_all(engine)
stmt = insert(user_table).values(name="spongebob", fullname="Spongebob Squarepants")
print(stmt)
with engine.connect() as conn:
result = conn.execute(stmt)
# conn.commit()
Even without commit my logs are:
INSERT INTO user_account (name, fullname) VALUES (:name, :fullname)
2023-02-09 16:12:05,033 INFO sqlalchemy.engine.Engine INSERT INTO user_account (name, fullname) VALUES (%(name)s, %(fullname)s) RETURNING user_account.id
2023-02-09 16:12:05,034 INFO sqlalchemy.engine.Engine [generated in 0.00123s] {'name': 'spongebob', 'fullname': 'Spongebob Squarepants'}
2023-02-09 16:12:05,037 INFO sqlalchemy.engine.Engine COMMIT
And new object appears in the database.
I tried to set conn.execution_options(isolation_level="SERIALIZABLE")
and
create_engine(...).execution_options(isolation_level="SERIALIZABLE")
with no success
However when I set isolation_level
to "AUTOCOMMIT"
, logs are slightly different (so I'm sure isolation_level option is interpreted correctly):
INSERT INTO user_account (name, fullname) VALUES (:name, :fullname)
2023-02-09 16:17:35,889 INFO sqlalchemy.engine.Engine INSERT INTO user_account (name, fullname) VALUES (%(name)s, %(fullname)s) RETURNING user_account.id
2023-02-09 16:17:35,890 INFO sqlalchemy.engine.Engine [generated in 0.00132s] {'name': 'spongebob', 'fullname': 'Spongebob Squarepants'}
2023-02-09 16:17:35,893 INFO sqlalchemy.engine.Engine COMMIT using DBAPI connection.commit(), DBAPI should ignore due to autocommit mode
sqlalchemy.__version__
'1.4.46'
What's the reason of such behavior?
What do I not understand?
What am I missing?
Thanks
IMPORTANT UPDATE
As @snakecharmerb pointed, with fututre=true
it works as expected (and this is the only significant difference with the docs).
engine = create_engine('...url', echo=True, future=True**)
So this flag changes autocommit behavior.
INSERT INTO user_account (name, fullname) VALUES (:name, :fullname)
2023-02-09 17:42:08,499 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-02-09 17:42:08,499 INFO sqlalchemy.engine.Engine INSERT INTO user_account (name, fullname) VALUES (%(name)s, %(fullname)s) RETURNING user_account.id
2023-02-09 17:42:08,500 INFO sqlalchemy.engine.Engine [generated in 0.00085s] {'name': 'spongebob', 'fullname': 'Spongebob Squarepants'}
<sqlalchemy.engine.cursor.CursorResult object at 0x7fef30f76ac0>
2023-02-09 17:42:10,511 INFO sqlalchemy.engine.Engine ROLLBACK
It answers my question mostly, but I'm still curious if I can have similar behavior without future=True
, because I cannot turn it on (for the project I work on) yet
Upvotes: 1
Views: 2270
Reputation: 816
Ok. Now it's clear. autocommit
and isolation_level
are different things. (They should be related, but that is out of the scope of the current question)
autocommit
is off by default if future=True
, and on by default otherwise.future=True
but still want autocommit
to be off you have 2 options (at least):2.1 Pass autocommit=false
to connection
:
with engine.connect().execution_options(autocommit=False) as conn
2.2 Pass autocommit=false
to engine
:
engine = create_engine('...dburl', echo=True).execution_options(autocommit=False)
Upvotes: 1