cloning bug in select

Issue #2453 resolved
Mike Bayer repo owner created an issue
#!/usr/bin/env python
# encoding: utf-8

# This is an illustration of a problem with column_properties where
# the from_obj contains joined aliased tables.

from sqlalchemy import Table, Column, Integer, ForeignKey, MetaData
from sqlalchemy import select
from sqlalchemy.sql.util import _deep_deannotate

metadata = MetaData()

orders = Table(
    'orders', metadata,
    Column('order_id', Integer, primary_key=True),
)

item = Table(
    'item', metadata,
    Column('item_id', Integer, primary_key=True),
    Column('order_id', Integer, ForeignKey('orders.order_id')),
)

a = item
b = a.outerjoin(orders)
s = select([a.c.item_id](a.c.item_id), from_obj=b)

a = item.alias()
b = a.outerjoin(orders)
s = select([a.c.item_id](a.c.item_id), from_obj=b)

print s
# XXX Not OK. Look at the FROM clause of this select
print _deep_deannotate(s)

Comments (5)

  1. Mike Bayer reporter

    patch:

    diff -r 7142a17291deba2eb9d4a2b30e1635129c2284ea lib/sqlalchemy/sql/expression.py
    --- a/lib/sqlalchemy/sql/expression.py  Wed Mar 21 22:58:55 2012 -0400
    +++ b/lib/sqlalchemy/sql/expression.py  Fri Mar 30 09:45:30 2012 -0400
    @@ -4800,10 +4800,22 @@
             """
             froms = self._froms
    
    +        # FROM objects that are being replaced by something else,
    +        # typically a JOIN involving that FROM
             toremove = set(itertools.chain(*[for f in froms](f._hide_froms)))
             if toremove:
    +            # if we're maintaining clones of froms,
    +            # add the copies out to the toremove list
    +            if self._from_cloned:
    +                toremove.update(
    +                    self._from_cloned[f](f) for f in 
    +                    toremove.intersection(self._from_cloned)
    +                )
    +            # filter out to FROM clauses not in the list,
    +            # using a list to maintain ordering
                 froms = [for f in froms if f not in toremove](f)
    
    +
             if len(froms) > 1 or self._correlate:
                 if self._correlate:
                     froms = [f for f in froms if f not in _cloned_intersection(froms,
    
  2. Mike Bayer reporter
    • changed status to open
    • removed status

    OK we still need to do that extra "toremove" logic for the case where _deep_deannotates are nested....

    mytable2 = table2.alias()
    
    s = select(
        [       _deep_deannotate(
                select(
                    [
                        _deep_deannotate(
                            select(
                                [ mytable2.c.t2_id ](
    ),
                                from_obj=table1.join(mytable2)
                            ).as_scalar()
                        ),
                    ]
                ).as_scalar()
            )
        ],
    )
    

    which would be if you're nesting column_property() objs together

    another razor thin edge ..

  3. Log in to comment