SQL expression in ORM update only look for ClauseElement, not __clause_element__()

Issue #3802 resolved
Mike Bayer repo owner created an issue
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)
    not_pk = Column(Integer)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

a1 = A(not_pk=1)
s = Session(e)

s.add(a1)
s.commit()

# works
a1.not_pk = A.not_pk.__clause_element__()
s.commit()

# fails
a1.not_pk = A.not_pk
s.commit()

Comments (1)

  1. Mike Bayer reporter

    Check for clause_element() in ORM insert/update

    ORM attributes can now be assigned any object that is has a __clause_element__() attribute, which will result in inline SQL the way any :class:.ClauseElement class does. This covers other mapped attributes not otherwise transformed by further expression constructs.

    As part of this, it was considered that we could add clause_element() to ClauseElement, however this causes endless loops in a "while" pattern and this pattern has been identified in third party libraries. Add a test to ensure we never make that change.

    Change-Id: I9e15b3f1c4883fd3909acbf7dc81d034c6e3ce1d Fixes: #3802

    → <<cset 09b685b24b19>>

  2. Log in to comment