-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Closed
Labels
bugSomething isn't workingSomething isn't workingdmlINSERT, UPDATE, DELETE, often with ORMINSERT, UPDATE, DELETE, often with ORMnear-term releaseaddition to the milestone which indicates this should be in a near-term releaseaddition to the milestone which indicates this should be in a near-term releaseorm
Milestone
Description
Discussed in #11911
from sqlalchemy import Column
from sqlalchemy import Computed
from sqlalchemy import create_engine
from sqlalchemy import engine
from sqlalchemy import insert
from sqlalchemy import Integer
from sqlalchemy import update
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import declared_attr
from sqlalchemy.orm import Session
engine = create_engine("postgresql://scott:tiger@localhost/test", echo="debug")
class BaseTable(DeclarativeBase):
@declared_attr
def __tablename__(cls) -> str:
return cls.__name__.lower()
class Tablichka(BaseTable):
id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
quantity = Column(Integer, nullable=False)
price = Column(Integer, nullable=False)
total_cost = Column(Integer, Computed("quantity * price"))
BaseTable.metadata.drop_all(engine)
BaseTable.metadata.create_all(engine)
with Session(engine) as session:
statement = (
insert(Tablichka).values(quantity=2, price=100).returning(Tablichka)
)
obj = (session.execute(statement)).scalar_one()
assert obj.total_cost == 200
statement = (
update(Tablichka)
.execution_options(populate_existing=True)
.values(quantity=4, price=100)
.returning(Tablichka)
)
obj = (session.execute(statement)).scalar_one()
assert obj.total_cost == 400
patch
diff --git a/lib/sqlalchemy/orm/bulk_persistence.py b/lib/sqlalchemy/orm/bulk_persistence.py
index 9a14a7ecf..5e565f717 100644
--- a/lib/sqlalchemy/orm/bulk_persistence.py
+++ b/lib/sqlalchemy/orm/bulk_persistence.py
@@ -646,6 +646,7 @@ class BulkUDCompileState(ORMDMLState):
_eval_condition = None
_matched_rows = None
_identity_token = None
+ _populate_existing: bool = False
@classmethod
def can_use_returning(
@@ -678,6 +679,7 @@ class BulkUDCompileState(ORMDMLState):
{
"synchronize_session",
"autoflush",
+ "populate_existing",
"identity_token",
"is_delete_using",
"is_update_from",
@@ -1592,10 +1594,20 @@ class BulkORMUpdate(BulkUDCompileState, UpdateDMLState):
bind_arguments: _BindArguments,
conn: Connection,
) -> _result.Result:
+
update_options = execution_options.get(
"_sa_orm_update_options", cls.default_update_options
)
+ if update_options._populate_existing:
+ load_options = execution_options.get(
+ "_sa_orm_load_options", QueryContext.default_load_options
+ )
+ load_options += {"_populate_existing": True}
+ execution_options = execution_options.union(
+ {"_sa_orm_load_options": load_options}
+ )
+
if update_options._dml_strategy not in (
"orm",
"auto",
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingdmlINSERT, UPDATE, DELETE, often with ORMINSERT, UPDATE, DELETE, often with ORMnear-term releaseaddition to the milestone which indicates this should be in a near-term releaseaddition to the milestone which indicates this should be in a near-term releaseorm