On Aug 11, 2010, at 1:19 PM, botz wrote:

> Thanks for that... I didn't manage to get it to work straight off, but
> it seems like I'm close.
> 
> Tried a couple things just to force it to behave as I wanted.
> 
> 
> # defined the selectable
> selectable = select( [ sql.column( 'x' ), sql.column('y')],
>                               from_obj =
> [ func.foo_props(bindparam( 'x' )) ] ,
>                               bind=...
>                               ).alias( 't')
> 
> 
> # mapping
> mapper( FooProps , selectable  , primary_key = [ selectable.c.x ] )
> 
> this fails with:
> InvalidRequestError: Could not find any Table objects in mapped table
> 'SELECT x,y FROM foo_props(%(param_1)s)'
> 
> #in sqlalchemy.orm.mapper the find_tables() call defaults to
> include_aliases = False, forced it to be true:
> 
>  def _configure_pks(self):
>        self.tables =
> sqlutil.find_tables(self.mapped_table,include_aliases=True)
> 
> (include_selectable = True worked also)

I'd have to spend some time thinking about what options exist there.    It 
might be better that the recipe for "mapping to a function" be done more 
similarly to http://www.sqlalchemy.org/trac/wiki/UsageRecipes/Views, where we 
are using a table() object on the inside + custom compilation.   it would at 
least eliminate one level of subquerying.   But also I think the whole 
"self.tables" requirement is probably not even needed (#1876).


> 
> then define the relationship:
> 
> mapper( Foo , foo_table, properties = dict( props =
> relation( FooProps,
> 
> primaryjoin = foo_table.c.x = selectable.c.x, foreignkey =
> [ selectable.c.x ] )))
> 
> 
> So now when I invoke the relationship
> a.foo
> 
> there a call:
> 
> SELECT  t.x, t.y
> FROM (SELECT x,y
> FROM foo_props(%(x)s)) AS t
> WHERE %(param_1)s = t.x
> 
> but only the param_1 is defined in the parameters to the call.  I can
> hack it by just setting the initial bindparam('x') to be
> bindparam('param1'),
> but that's not really ideal obviously

What is implied by relationship() is that you're joining and limiting a full 
set of records using a join condition.  This implies that the mapped selectable 
would be returning a set of rows corresponding to all possible child 
collections, not just the collection of a single parent based on a bind.     So 
here you'd perhps have to wrap your function into a correlated subquery to 
produce that effect, or rewrite the function so that it returns all possible 
child collections with an extra set of columns indicating those of the parents. 
  There is a recipe to get binds into a relationship, but not for this same use 
case, at http://www.sqlalchemy.org/trac/wiki/UsageRecipes/GlobalFilter -  it 
probably is also not what you're looking for here.

So if all those options and not feasable here, then you are gaining nothing by 
using relationship() in the first place - its already a "viewonly" 
relationship, and for the case of "eager loading" as well as any kind of 
expression construction, which is the other reason you'd use relationship and 
not just a method on your class, those aren't feasable either since again, your 
mapped function doesn't represent the full set of possible results.  

For an attribute that is used for nothing other than Foo.foobars hitting the 
database and returning an iterable, you don't need relationship().    you just 
put a method / @property on your Foo class that aquires the current session 
using object_session(self).   If you also wanted class level expressions, such 
as query(Foo).filter(Foo.foobars.any(...)), to have some kind of meaning that 
you define, that can also be constructed without using relationship() using 
some techniques that I plan on adding to a new extension soon, which builds 
upon examples/derived_attributes.   



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

Reply via email to