Skip to content

populate_existing ignored for bulk UPDATE, DELETE #11912

@zzzeek

Description

@zzzeek

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

No one assigned

    Labels

    bugSomething isn't workingdmlINSERT, UPDATE, DELETE, often with ORMnear-term releaseaddition to the milestone which indicates this should be in a near-term releaseorm

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions