can't use SQL expression for PK col

Issue #3801 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 + 0
s.commit()

# fails
a1.id = A.id + 0
s.commit()

Comments (4)

  1. Mike Bayer reporter

    this is easy. the line below is unnecessary as the following assertion passes with current tests (obviously not this one):

    diff --git a/lib/sqlalchemy/orm/persistence.py b/lib/sqlalchemy/orm/persistence.py
    index 0b029f4..04ef376 100644
    --- a/lib/sqlalchemy/orm/persistence.py
    +++ b/lib/sqlalchemy/orm/persistence.py
    @@ -530,7 +530,7 @@ def _collect_update_commands(
                         else:
                             # else, use the old value to locate the row
                             pk_params[col._label] = history.deleted[0]
    -                        params[col.key] = history.added[0]
    +                        assert params[col.key] is history.added[0]
                     else:
                         pk_params[col._label] = history.unchanged[0]
                     if pk_params[col._label] is None:
    

    that is, we already grabbed the value above. So just remove the line and we are good:

    diff --git a/lib/sqlalchemy/orm/persistence.py b/lib/sqlalchemy/orm/persistence.py
    index 0b029f4..0099ba6 100644
    --- a/lib/sqlalchemy/orm/persistence.py
    +++ b/lib/sqlalchemy/orm/persistence.py
    @@ -530,7 +530,6 @@ def _collect_update_commands(
                         else:
                             # else, use the old value to locate the row
                             pk_params[col._label] = history.deleted[0]
    -                        params[col.key] = history.added[0]
                     else:
                         pk_params[col._label] = history.unchanged[0]
                     if pk_params[col._label] is None:
    
  2. Mike Bayer reporter

    of course on SQLite we can't find the row afterwards, that's not part of the bug here. changing that to "+0"

  3. Mike Bayer reporter

    Allow SQL expressions to be set on PK columns

    Removes an unnecessary transfer of modified PK column value to the params dictionary, so that if the modified PK column is already present in value_params, this remains in effect. Also propagate a new flag through to _emit_update_statements() that will trip "return_defaults()" across the board if a PK col w/ SQL expression change is present, and pull this PK value in _postfetch as well assuming we're an UPDATE.

    Change-Id: I9ae87f964df9ba8faea8e25e96b8327f968e5d1b Fixes: #3801

    → <<cset f8ecdf47f097>>

  4. Log in to comment