regression in 0.9's "order by collapse" logic

Issue #3188 resolved
Mike Bayer repo owner created an issue

seems to be non-deterministic

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class C(Base):
    __tablename__ = 'c'

    id = Column(Integer, primary_key=True)
    a_id = Column(ForeignKey('a.id'))
    b_id = Column(ForeignKey('b.id'))

class B(Base):
    __tablename__ = 'b'

    id = Column(Integer, primary_key=True)

B.b = column_property(
        select([func.max(C.id)]).where(C.b_id == B.id).correlate(B)
    )


b1 = aliased(B)

sess = Session()

#print sess.query(B, b1).order_by(B.b)
print sess.query(B, b1).order_by(b1.b)

output, based on if you uncomment that one query, for the second query, is:

SELECT b.id AS b_id, (SELECT max(c.id) AS max_1 
FROM c 
WHERE c.b_id = b.id) AS anon_1, b_1.id AS b_1_id, (SELECT max(c.id) AS max_2 
FROM c 
WHERE c.b_id = b_1.id) AS anon_2 
FROM b, b AS b_1 ORDER BY anon_1

e.g. it is ordering by the wrong expression.

there's a lot going on with order_by right now so im not sure this can be in 0.9, will need to see if something can be backported.

Comments (2)

  1. Mike Bayer reporter
    • enhance ClauseAdapter / ColumnAdapter to have new behaviors with labels. The "anonymize label" logic is now generalized to ClauseAdapter, and takes place when the anonymize_labels flag is sent, taking effect for all .columns lookups as well as within traverse() calls against the label directly.
    • traverse() will also memoize what it gets in columns, so that calling upon traverse() / .columns against the same Label will produce the same anonymized label. This is so that AliasedClass produces the same anonymized label when it is accessed per-column (e.g. SomeAlias.some_column) as well as when it is applied to a Query, and within column loader strategies (e.g. query(SomeAlias)); the former uses traverse() while the latter uses .columns
    • AliasedClass now calls onto ColumnAdapter
    • Query also makes sure to use that same ColumnAdapter from the AliasedClass in all cases
    • update the logic from 0.9 in #1068 to make use of the same _label_resolve_dict we use for #2992, simplifying how that works and adding support for new scenarios that were pretty broken (see #3148, #3188)

    → <<cset 7950270cf2b1>>

  2. Log in to comment