Re: [sqlalchemy] Mixed inheritance mapping and multiple binds

2010-01-19 Thread Ross Vandegrift
On Mon, Jan 18, 2010 at 07:24:45PM -0500, Michael Bayer wrote:
 The argument against the tables being broken out in get_bind() is
 partially one of implementation performance and partially one of
 ambiguity, i.e. join of a to b, which table wins ?  Neither argument
 is completely compelling, though a decision on changing this
 behavior is not likely to happen hastily.  Also, we don't support
 persisting one half of the object in one database and the other half
 in another.   Which again is something that is certainly possible
 architecturally, just would require a lot of thought such that it
 doesn't get in the way performancewise of the vast majority of cases
 that don't want to do that.

Wow, sounds like I stumbled on a bit of a deep question here.  Sounds
like a kinda cool idea, pushing parts of objects across databases.
Fortunately, I have no need for that functionality.

 On Jan 18, 2010, at 6:27 PM, Ross Vandegrift wrote:
  engine = create_engine('sqlite:///:memory:', echo=True)
  metadata.create_all(engine)
  binds = { device_table : engine,
   switch_table : engine }
  
 
 
 Currently its looking at the mapped table of each object's class,
 which in this case is a join object, not either of the Table objects
 by themselves.  That might not be ideal, but in any case its better
 if you bind classes and not tables to each engine.  i.e.:
 
 binds = {
 DeviceBase:engine,
 Switch:engine
 }

Wow, talk about a simple fix!  Works perfectly when I concoct things
like that.  Michael, as usual, you are amazing.

Ross

-- 
Ross Vandegrift
r...@kallisti.us

If the fight gets hot, the songs get hotter.  If the going gets tough,
the songs get tougher.
--Woody Guthrie


signature.asc
Description: Digital signature


[sqlalchemy] Re: Dynamic mapper issue

2010-01-19 Thread Kalium
Thanks Michael, I'm going to take a closer look at this and rework my
code.

Cheers
Raymond

On Nov 27 2009, 12:56 pm, Michael Bayer mike...@zzzcomputing.com
wrote:
 On Nov 26, 2009, at 2:05 AM, Kalium wrote:

  Hi, I'm coming to grief trying to create aMapperon the fly.

  At first I tried this

  classDynamic(object):
                     pass

 Dynamic.mapper=mapper(Dynamic, self.j);

  self.j is a join statement. This now maps all the columns from the
  tables in the join statement. Which is fine. Except that in the SQL
  query it looks something like  SELECT table1.id AS id, table2.id AS
  id etc etc. So that won't work as the columns don't have alias'.

 the join() by itself is automatically disambiguating so you shouldn't have 
 such an issue:

 from sqlalchemy import *
 from sqlalchemy.orm import *

 m = MetaData(e)

 t1 = Table('t1', m, Column('id', Integer, primary_key=True))
 t2 = Table('t2', m, Column('id', Integer, primary_key=True))

 j = t1.join(t2, t1.c.id==t2.c.id)

 # j now has j.c.t1_id, j.c.t2_id
 print j.c.t1_id, j.c.t2_id

 returns:

 t1.id t2.id

 now map:

 class C(object):
     pass

 mapper(C, j)

 print create_session().query(C)

 returns:

 SELECT t1.id AS t1_id, t2.id AS t2_id
 FROM t1 JOIN t2 ON t1.id = t2.id

 the map of C will have a single attribute id on it, which is based on that 
 name.  in this case, that's fine since the two id columns are equated, and 
 you'd want them to be under one attribute.  If you didn't, you can set up the 
 mapping explicitly with the names you prefer:

 m = MetaData(create_engine('sqlite://'))

 t1 = Table('t1', m, Column('id', Integer, primary_key=True), Column('data', 
 String))
 t2 = Table('t2', m, Column('id', Integer, primary_key=True), Column('data', 
 String))
 m.create_all()

 j = t1.join(t2, t1.c.id==t2.c.id)

 class C(object):
     pass

 mapper(C, j, properties={
     't1data':t1.c.data,
     't2data':t2.c.data

 })

 s = sessionmaker()()
 c1 = C()
 c1.t1data='foo'
 c1.t2data='bar'
 s.add(c1)
 s.commit()
 print s.execute(select * from t1 join t2 on t1.id=t2.id,mapper=C).fetchall()

 returns:

 [(1, u'foo', 1, u'bar')]

 above, themapperfor C has a single attribute id representing t1.c.id and 
 t2.c.id, but separate t1data and t2data attributes representing t1.c.data 
 and t2.c.data, respectively.



  Next I tried something like this

 Dynamic.mapper=mapper(Dynamic,select(fields_to_select,from_obj=
  [self.j]),primary_key=[table1.c.id,table2.c.id,table3.c.id])

 here, you've mapped to a select() construct - that is your selectable.  The 
 mistake here is that you used columns for primary_key which are from your 
 tables - which are represented within the internal FROM clause of your 
 select() but are not the columns it publically exposes in its columns clause. 
     Any columns you specify to primary_key must be in terms of the mapped 
 selectable's exported columns clause, i.e. myselect.c.table1_id, 
 myselect.c.table2_id, myselect.c.table3_id.   Specifying use_labels on your 
 select() construct will allow the column names it exports in its c 
 collection to be prepended with the table name, the same way that the join() 
 does automatically.  

 But also, if your select() already has all the PK fields from the three 
 tables represented, the primary key columns will automatically be pulled out 
 in the mapping so there is probably no need for the primary_key argument.
-- 
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.