[sqlalchemy] eager load polymorphic relation

2013-05-17 Thread me
using python 2.7, sqla 0.7.9, postgresql 9.1

i'm trying to eager load a relationship to a polymorphic target (the target
uses joined table inheritance).

here is example:

http://pastebin.com/xSiHS4QW

and this is output:

SELECT
...
FROM container
LEFT OUTER JOIN root AS root_1 ON root_1.id = container.root_id

no type1, not type2?

looks like with_polymorphic mappig arg controls that:

http://pastebin.com/FfmJSZWc

and this is output:

SELECT ...
FROM container
LEFT OUTER JOIN (
SELECT ...
FROM root
LEFT OUTER JOIN type1 ON root.id = type1.id
LEFT OUTER JOIN type2 ON root.id = type2.id
) AS anon_1 ON anon_1.root_id = container.root_id

but i thought i'd get:

SELECT ...
FROM container
LEFT OUTER JOIN root AS root_1 ON root_1.id = container.root_id
LEFT OUTER JOIN type1 ON root.id = type1.id
LEFT OUTER JOIN type2 ON root.id = type2.id

this is not problem for small sets but for bulk ops either lazy loading or
subselect are much slower.

it looks like many have run into this. i tried using contains_eager but 
though
that joins how i want it still does not load the entire target object (just 
base):

c = Container
.query
.join(Container.root)
.outerjoin(type1, root.c.id == type1.c.id)
.outerjoin(type2, root.c.id == type2.c.id)
.options(contains_eager(Container.root))
.first()
c.root.field2 # field2 was not mapped so will do SELECT

is there a way to build a query that eagerly loads the whole entity?

q = Session.query ...
c = q.first()
c.root.field2 # already loaded so not SELECT

thanks

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] joined table inhertiance and eager loading self-referencing relationships

2012-10-07 Thread me
using python 2.7, sqla 0.7.9, postgresql 9.1

i've setup joined table inheritance and wanted an eager loaded relationship 
from one of the derived objects to another derived object. when i do that i 
get what seems to be a really inefficient query.

here is the minimal setup:

http://pastebin.com/yS7gDfju

and this is the output:

SELECT
...
FROM root
JOIN type2 ON root.id = type2.id
LEFT OUTER JOIN (SELECT root.id AS root_id, root.type AS root_type, 
type1.id AS type1_id, type1.field1 AS type1_field1 
 FROM root JOIN type1 ON root.id = 
type1.id) AS anon_1 ON type2.type1_id = anon_1.type1_id

what i expected was:

SELECT
...
FROM root
JOIN type2 ON root.id = type2.id
LEFT OUTER JOIN root as root_1 ON root_1.id = type2.type1_id
LEFT OUTER JOIN type1 ON type1.id = root_1.id

which runs *much* faster for the data sets i've tried.

is there a way to force the relationship to generate the 2nd form? or am i 
doing something i shouldn't?

thanks

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/0laXtaxdh8UJ.
To post to this group, send email to sqlalchemy@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.



[sqlalchemy] Re: sqla 0.6.4, orm, problem with self-referring joins

2010-09-20 Thread me
=AliasedA1A1))
#AliasedB1 = orm.aliased(B)
#q = q.join((AliasedB1,
A.some_b)).options(orm.contains_eager(A.some_b, alias=AliasedB1))

print q
=

On Sep 20, 7:56 am, Michael Bayer mike...@zzzcomputing.com wrote:
 On Sep 19, 2010, at 11:59 PM, me wrote:



  when i apply multiple joins to orm query, one of them self-referring,
  using (target, property) form sqla generates the wrong join criteria
  by selecting aliased table for the left side of the join.

  sess = Session()
  AliasedA = orm.aliased(A)
  q = sess.query(A)
  q = q.join((AliasedA, A.some_a)).options(orm.contains_eager(A.some_a,
  alias=AliasedA))
  q = q.join((B, A.some_b)).options(orm.contains_eager(A.some_b))
  print q

  --

  SELECT
     b.id AS b_id, b.a_id AS b_a_id, b.b_data AS b_b_data,
     a_1.id AS a_1_id, a_1.a_data AS a_1_a_data,
     a.id AS a_id, a.a_data AS a_a_data
  FROM a
     JOIN assoc AS assoc_1 ON a.id = assoc_1.left_id
     JOIN a AS a_1 ON assoc_1.right_id = a_1.id
     JOIN b ON b.a_id = a_1.id
  

  here i expected JOIN b ON b.a_id = a.id not JOIN b ON b.a_id =
  a_1.id.

 This one is fun.   join() always joins from the most recent FROM that it can. 
  So here you want to first call reset_joinpoint() before calling join() 
 again.     The other traditional way is to use the separate orm.join() 
 construct in conjunction with select_from(), though we are continuing to 
 refine join() so that wont be needed (I eventually would like it to allow 
 (left, right, onclause)...but we need to get everyone on a modernized calling 
 form first).

  perhaps weight relations so that those that introduce alias are
  applied in right order?

 interestingbut this is really a 50/50 guess.   Its just as likely someone 
 really meant to join from AliasedA to B.  

-- 
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.



[sqlalchemy] sqla 0.6.4, orm, problem with self-referring joins

2010-09-19 Thread me
when i apply multiple joins to orm query, one of them self-referring,
using (target, property) form sqla generates the wrong join criteria
by selecting aliased table for the left side of the join.

tried sqla 0.5.8 and 0.6.4, same result.

e.g. for sqla 0.6.4

from sqlalchemy import create_engine, Table, MetaData, orm, Column,
Integer, ForeignKey, String
from sqlalchemy.interfaces import PoolListener

class Listener(PoolListener):
def connect(self, dbapi_con, con_record):
dbapi_con.execute(PRAGMA foreign_keys=ON)

engine = create_engine(
 sqlite:///:memory:,
 listeners=[Listener()],
 echo=True)

Session = orm.sessionmaker(bind=engine)

metadata = MetaData()

a_table = Table(
a, metadata,
Column(id, Integer, primary_key=True),
Column(a_data, String)
)

assoc_table = Table(
assoc, metadata,
Column(left_id, ForeignKey(a_table.c.id)),
Column(right_id, ForeignKey(a_table.c.id))
)

b_table = Table(
b, metadata,
Column(id, Integer, primary_key=True),
Column(a_id, ForeignKey(a_table.c.id)),
Column(b_data, String)
)

class B(object):
pass
orm.mapper(B, b_table)

class A(object):
pass
orm.mapper(
A, a_table,
properties={
some_a: orm.relation(
  A,
  primaryjoin=a_table.c.id ==
assoc_table.c.left_id,
  secondary=assoc_table,
  secondaryjoin=assoc_table.c.right_id ==
a_table.c.id),
some_b: orm.relation(
  B,
  primaryjoin=b_table.c.a_id == a_table.c.id)
}
)

sess = Session()
AliasedA = orm.aliased(A)
q = sess.query(A)
q = q.join((AliasedA, A.some_a)).options(orm.contains_eager(A.some_a,
alias=AliasedA))
q = q.join((B, A.some_b)).options(orm.contains_eager(A.some_b))
print q

--

SELECT
b.id AS b_id, b.a_id AS b_a_id, b.b_data AS b_b_data,
a_1.id AS a_1_id, a_1.a_data AS a_1_a_data,
a.id AS a_id, a.a_data AS a_a_data
FROM a
JOIN assoc AS assoc_1 ON a.id = assoc_1.left_id
JOIN a AS a_1 ON assoc_1.right_id = a_1.id
JOIN b ON b.a_id = a_1.id


here i expected JOIN b ON b.a_id = a.id not JOIN b ON b.a_id =
a_1.id.

looks like the whole query is anaylzed for a_1 alias based on
join_to_left=True set in 0.6.4/orm/query.py, ln 1341.

i can change order that joins are applied to avoid this OR replace
property A.bs with explicit join condition (i.e. A.id = B.a_id) but
for generated queries this is not always easy/convenient to do.
perhaps weight relations so that those that introduce alias are
applied in right order?

is this a bug or expected? is there a way to avoid this behavior when
using multiple (target, property) joins?

thanks.

-- 
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.



[sqlalchemy] Re: 0.55, orm, varying relation join on criteria

2009-09-15 Thread me

thanks for the (insanely fast) help! wanted to avoid doing something
unnecessarily odd.

i ended up wrapping the relation in an object proxy when passing it to
the join. the proxy ANDs additional criterion into the primary or
secondary join attributes of the relation based on what is supplied
when creating the proxy. though clearly odd it seem to generally work.
i'm not sure if this may break orm magic somewhere down the line...

code looks  like this:

query(User).outerjoin((Email, RelationProxy(User.emails, Email.name !=
bogus)))

the object proxy code is based on the following if anyone's
interested:

http://code.activestate.com/recipes/496741/
http://code.activestate.com/recipes/519639/

On Sep 14, 2:13 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 me wrote:

  For certain orm queries with a 1-to-many relation i want to left outer
  join and then update the on-clause for that relation. Since the
  criteria changes between queries I cannot fix the join criteria when
  specifying my object/table mappings.

  For example:
      tables: user, email
      relation:  user.emails (1-many)

      select *
      from user
      left outer join email on email.user_id = user.id and email.name
  like '%hello%'

  While this is easy to write as a one off query in my case I need to be
  able to add variable filtering to the join on-clause and in a way that
  hopefully works for more complex relations.

  So e.g. if I have a query built like this:
      query(user).outerjoin((email, emails))

  Is there a general way to add to the primary/secondary join criteria
  that is pulled from this emails relation? Or is there a better way to
  express this in SA that I've missed?

 the contract of query.outerjoin(SomeClass.property) is that you're doing a
 plain join from A to B along pre-established routes.   If you'd like the
 criterion of the ON clause to be customized, the standard route is to
 spell out the entire thing you want completely.   The only potential time
 saver here would be if you held onto the primaryjoin aspect of the
 relation and used it in an AND clause, which at first looks like:

 query(User).outerjoin((Email, and_(email_primary_join, other criterion)))

 the next level would be that you'd pull email_primary_join from the
 mapping.  You can get at this via User.emails.property.primaryjoin.

 at the moment that's as automated as it gets as far as what's built in.
--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] 0.55, orm, varying relation join on criteria

2009-09-14 Thread me

For certain orm queries with a 1-to-many relation i want to left outer
join and then update the on-clause for that relation. Since the
criteria changes between queries I cannot fix the join criteria when
specifying my object/table mappings.

For example:
tables: user, email
relation:  user.emails (1-many)

select *
from user
left outer join email on email.user_id = user.id and email.name
like '%hello%'

While this is easy to write as a one off query in my case I need to be
able to add variable filtering to the join on-clause and in a way that
hopefully works for more complex relations.

So e.g. if I have a query built like this:
query(user).outerjoin((email, emails))

Is there a general way to add to the primary/secondary join criteria
that is pulled from this emails relation? Or is there a better way to
express this in SA that I've missed?

Thanks,
M
--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: 0.5.2, orm, deferring joined columns during query construction

2009-03-14 Thread me

Thanks for the help!

Specifying path as a string  relative to the root of the query
properly defers the columns. Specifying path information with
qualified object attributes (your second suggestion) also works. So
everything works, I didn't

Is this approach correct for cases where you end up deferring a large
number of columns (e.g. 20)? Is there perhaps a more efficient way to
bulk defer/undefer columns (whether these are columns of related
children or the root) short of specifying that information when
initially creating the query (e.g. session.query(A.b, A.c, B.x, ...)).
I avoided doing that as I wanted an instance of a root object and the
query.one() problem.

Thanks,
M

On Mar 12, 8:56 am, Michael Bayer mike...@zzzcomputing.com wrote:
 me wrote:

  2] Using path to the joined column:
  query = query.option(defer(a.s1_relation.col1), defer
  (a.s1_alias_relation.col2),...)

  2
  Simply doesn't work for me (i.e. the columns i'm deferring are clearly
  in the echoed sql).

 try not putting a in there.  defer() is based on an older usage of Query
 that assumes one entity at the root, i.e.
 s.query(SomeClass).options(defer(relation.somecol)).

  I also tried passing instrumented object attributes to defers like
  this: query = query.option(defer(S1.y), defer(S1Alias.x)) but that
  failed with an exception about e.g. S1 not being found in the mapper.
  I tried adding them to the query like this: query.add_entity(S1) but
  that didn't help.

 needs a path from the root:   defer(SomeClass.foo, FooClass.bar)

--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] 0.5.2, orm, deferring joined columns during query construction

2009-03-12 Thread me

To optimize a query I'm attempting to defer columns from joined tables
I know I'm not going to need. The columns from joined tables to defer
varies from query to query so I can't specify this when setting up my
object/table mappings.

I'm able to do this just fine for columns of the primary table like
this: query = query.option(defer(x)).

It appears there are two ways to do the same for joined columns:

1] When specifying entities
query = a_session.query(P, S1.x, S2.y, S1Alias.x)...

2] Using path to the joined column:
query = query.option(defer(a.s1_relation.col1), defer
(a.s1_alias_relation.col2),...)

1
Seemed easy enough but i ran into problems when using this in
conjunction with query.one(): it would raise exceptions that the
result set had more than one row. I really just want to pull the
entity object (preloaded with relevant column values, some from
related tables) and then extract that to a dictionary. So pulling
S1.x, S2.y, S1Alias.x into the result, making it a tuple, seems a
little strange.

2
Simply doesn't work for me (i.e. the columns i'm deferring are clearly
in the echoed sql).

I also tried passing instrumented object attributes to defers like
this: query = query.option(defer(S1.y), defer(S1Alias.x)) but that
failed with an exception about e.g. S1 not being found in the mapper.
I tried adding them to the query like this: query.add_entity(S1) but
that didn't help.

Apart from the unwanted columns the emitted SQL is what i expect and
looks like:
SELECT bunch of columns
FROM parent
LEFT OUTER JOIN parent_child AS series_child_1 ON series.id =
series_child_1.series_id
LEFT OUTER JOIN child ON series_child_1.child_id = child.id
-- primary child
INNER JOIN child AS child_1 ON child_1.id =
series.parent_child_id
WHERE series.id = 1000 AND child.name LIKE 'prefix%'

Am i missing something? Is there a way to specify joined column defers
during query construction? Do i need to write a custom MapperProperty
to do this?

Thanks,
M

--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---