This caught me out a couple of weeks ago, and I've seen a couple of
other similar questions as well. You need to add 'correlate=False' to
the nested select.

I wonder if this should be added to the FAQ?

Hope that helps,

Simon

-----Original Message-----
From: sqlalchemy@googlegroups.com [mailto:[EMAIL PROTECTED]
On Behalf Of Koen Bok
Sent: 22 March 2007 10:47
To: sqlalchemy
Subject: [sqlalchemy] Re: Using mapper with custom select creates
unneeded subquery


Let me post some sample code with that:

mapper(Request, request_table, properties={
                'children' : relation(
                        Request,
        
primaryjoin=request_table.c.id_parent==request_table.c.id,
                        backref=backref("parent",
remote_side=[request_table.c.id])),
                'i': relation(Item,
primaryjoin=item_table.c.id==request_table.c.id_item,
backref='requests', lazy=True),
                [SOME MORE STUFF]
                'stock': relation(Stock, primaryjoin=and_(
        
request_table.c.id_item==stock_table.c.id_product,
        
request_table.c.id_location==stock_table.c.id_location,
        
request_table.c.id_stocktype==stock_table.c.id_stocktype),
                foreign_keys=[stock_table.c.id_product,
stock_table.c.id_location,
stock_table.c.id_stocktype])})

stock_request = select(
        [c for c in stock_table.c] + \
        [stock_table.c.quantity.op('-')
(func.sum(request_table.c.quantity)).label('unordered')] + \
        [stock_table.c.quantity.op('-')
(func.sum(request_table.c.allocation)).label('unallocated')],
        and_(
                request_table.c.id_item==stock_table.c.id_product,
                request_table.c.id_location==stock_table.c.id_location,
        
request_table.c.id_stocktype==stock_table.c.id_stocktype),
        group_by=[c for c in stock_table.c]).alias('stock_request')

mapper(Stock, stock_request, properties={
        'product': relation(Item,
primaryjoin=item_table.c.id==stock_table.c.id_product,
backref='_stock'),
        'location': relation(Item,
primaryjoin=item_table.c.id==stock_table.c.id_location),
        'stocktype': relation(StockType)})

If you need more, just let me know!

Koen

On Mar 22, 11:42 am, "Koen Bok" <[EMAIL PROTECTED]> wrote:
> Thanks for the reply! If the performance is about equal, that's fine!
>
> But I think I might have found a bug.
>
> When I make a selection it generates the following (faulty) SQL query:
>
> SELECT
>         stock_request.id_stocktype AS stock_request_id_stocktype,
>         stock_request.unordered AS stock_request_unordered,
>         stock_request.id_location AS stock_request_id_location,
>         stock_request.id_product AS stock_request_id_product,
>         stock_request.unallocated AS stock_request_unallocated,
>         stock_request.quantity AS stock_request_quantity,
>         stock_request.id AS stock_request_id FROM
>         (
>         SELECT
>                 stock.id AS id,
>                 stock.id_stocktype AS id_stocktype,
>                 stock.id_product AS id_product,
>                 stock.id_location AS id_location,
>                 stock.quantity AS quantity,
>                 (stock.quantity - sum(request.quantity)) AS unordered,
>                 (stock.quantity - sum(request.allocation)) AS
unallocated
>         FROM request
>         WHERE
>                 request.id_item = stock.id_product
>         AND
>                 request.id_location = stock.id_location
>         AND
>                 request.id_stocktype = stock.id_stocktype
>         GROUP BY
>                 stock.id,
>                 stock.id_stocktype,
>                 stock.id_product,
>                 stock.id_location,
>                 stock.quantity,
>                 stock.quantity
>         ) AS stock_request, stock
> WHERE
>         stock.id_product = 5
> AND
>         stock.id_location = 7
> AND
>         stock.id_stocktype = 1
> ORDER BY
>         stock_request.id
> LIMIT 1
>
> The FROM in the subquery should be: FROM request, stock
>
> The strange thing is that whenever I print the subquery's sql, it has 
> stock in the FROM and tehrefore is correct.
>
> Or am I not understanding it right?
>
> Koen
>
> On Mar 22, 2:58 am, Michael Bayer <[EMAIL PROTECTED]> wrote:
>
> > when you pass a selectable to the mapper, the mapper considers that 
> > selectable to be encapsulated, in the same way as a table is.  the 
> > Query cannot add any extra criterion to that selectable directly 
> > since it would modify the results and corrupt the meaning, if not 
> > the actual syntax, of the selectable itself.  therefore the mapper 
> > is always going to select * from (your selectable) - its the only 
> > way to guarantee the correct results.
>
> > the queries it generates, i.e. select * from (select * from ...)) 
> > will be optimized by the database's optimizer in most cases and 
> > should not add any overhead to your application.
>
> > On Mar 21, 2007, at 8:08 PM, Koen Bok wrote:
>
> > > My mapper looks like this:
>
> > > stock_unreserved = select(
> > >    [stock_table] + \
> > >    [stock_table.c.quantity.op('-') 
> > > (func.sum(request_table.c.quantity)).label('unordered')] + \
> > >    [stock_table.c.quantity.op('-') 
> > > (func.sum(request_table.c.allocation)).label('unallocated')],
> > >    and_(
> > >            request_table.c.id_item==stock_table.c.id_product,
> > >            request_table.c.id_location==stock_table.c.id_location,
> > >
request_table.c.id_stocktype==stock_table.c.id_stocktype),
> > >    group_by=[c for c in stock_table.c]).alias('stock_unreserved')
>
> > > mapper(Stock, stock_unreserved, properties={
> > >    'product': relation(Item,
> > > primaryjoin=item_table.c.id==stock_table.c.id_product,
> > > backref='_stock'),
> > >    'location': relation(Item,
> > > primaryjoin=item_table.c.id==stock_table.c.id_location),
> > >    'stocktype': relation(StockType)})
>
> > > Whenever I try to select an object through the mapper I would 
> > > think it would use the SQL from stock_unreserved which is:
>
> > > SELECT
> > >    stock.id,
> > >    stock.id_stocktype,
> > >    stock.id_product,
> > >    stock.id_location,
> > >    stock.quantity, (stock.quantity - sum(request.quantity)) AS 
> > > unordered,
> > >    (stock.quantity - sum(request.allocation)) AS unallocated FROM 
> > > stock, request WHERE request.id_item = stock.id_product AND 
> > > request.id_location = stock.id_location AND request.id_stocktype =

> > > stock.id_stocktype GROUP BY stock.id, stock.id_stocktype, 
> > > stock.id_product, stock.id_location, stock.quantity
>
> > > Selecting all objects by a plain select() on the mapper works
great!
> > > But when I make a selection it does a subquery on all the results
eg:
>
> > > SELECT * FROM (SELECT * FROM stock_unreserved) WHERE selection 
> > > criteria
>
> > > But I want it to append it to the other selection criteria without

> > > doing a subselect eg:
>
> > > SELECT * FROM stock_unreserved WERE ... AND ... + extra selection 
> > > criteria
>
> > > Is this possible at all?
>
> > > Many thanks!
>
> > > Koen




--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to