[sqlalchemy] Determine column properties created via declarative mixins

2011-10-17 Thread Robert Forkel
Hi all,
Using sqlalchemy 0.7.2 I created a couple of mixin classes (say Mixin)
to share columns declarations between model classes (say A and B).
Sometimes I have to create instances of type B initialized with the
values of an existing object of type A for the columns declared by
Mixin. I'd like to make this code extensible with respect to the
columns declared in Mixin, i.e. adding new columns to Mixin should
require updating this code.
Is there a way to find the names of column properties contributed by a
Mixin?
(I tried with checking Mixin.__dict__ for items of type
sqlalchemy.schema.Column, but this doesn't give foreign keys declared
via @declared_attr)
best regards
robert

-- 
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] Does the MRO matter when using declarative with mixins?

2011-10-17 Thread Russ
All the declarative examples have DeclarativeBase as the first/left base 
class.  Does it need to be?  I've swapped it in several code locations and 
experimented and it seems to be fine, but there's a lot going on with 
declarative and I'm vaguely paranoid about messing it up subtly by altering 
the MRO.

ie: This is normal, and is how all declarative examples are done:

class Foo(Base, MyMixin):
#snip

but is this also ok, or will it cause issues somehow?

class Foo2(MyMixin, Base):
#snip

The reason I'm looking at this is that I've got a case with multiple mixin 
classes, and when the top mixin used doesn't have an __init__ definition, 
but a lower level class does, having the declarative base first fails 
because it doesn't use a (*args, **kwargs) catchall.  I also wonder how 
super() will end up working out.

Since that last bit probably wasn't very clear, here is a small but full 
example of what I mean:
http://static.inky.ws/syn/335

Resolving the __init__ args issue is resolved by putting the Mixin first.  I 
just want to make sure it is fine.

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



Re: [sqlalchemy] Does the MRO matter when using declarative with mixins?

2011-10-17 Thread Michael Bayer

On Oct 17, 2011, at 11:38 AM, Russ wrote:

 All the declarative examples have DeclarativeBase as the first/left base 
 class.  Does it need to be?  I've swapped it in several code locations and 
 experimented and it seems to be fine, but there's a lot going on with 
 declarative and I'm vaguely paranoid about messing it up subtly by altering 
 the MRO.
 
 ie: This is normal, and is how all declarative examples are done:
 
 class Foo(Base, MyMixin):
 #snip
 
 but is this also ok, or will it cause issues somehow?
 
 class Foo2(MyMixin, Base):
 #snip

The MRO basically matters as much as it matters in any case.   If your mixin 
has an attribute that's not in a prior class within the MRO, that's the 
attribute that wins.   Declarative scans through the whole MRO at startup but 
pretty much keeps things the way they work anyway (deviations from that would 
be bugs).

Actually I usually put the mixins first, because you're overriding whatever is 
the base.  I should even change the docs in that regard, it's weird that they 
don't use that convention.   Looking now it's actually fairly awkward the way 
it is.

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



Re: [sqlalchemy] Does the MRO matter when using declarative with mixins?

2011-10-17 Thread Russ
Great - thanks for the response.   This was causing me more brain ache than 
I care to admit.  My paranoia was rooted in the fact that the docs did seem 
to go out of their way to put the Base first (without specifically saying 
so) which is awkward as you say.

Much appreciated.

-- 
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/-/gOZETa5S6CQJ.
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] History meta and unique issue

2011-10-17 Thread Damian
Hello!

I've run into an odd error whilst using the history meta.  I've got a
class which has two sub classes which define some additional columns.
The MainMeter class has a unique constraint on one of the colums.
When I have the history_meta create my history tables, the
trading_point_name column retains its unique constraint despite there
being a col.unique = False in the history meta which should disable
it.  I can't quite figure out why this is happening.  Any hints would
be appreciated!

class Meter(Base, BaseMixin):
__metaclass__ = VersionedMeta
__tablename__ = meters

id = sa.Column(sa.Integer, primary_key=True)
type = sa.Column(sa.Enum('main_meter', 'check_meter'))
# and so forth

class MainMeter(Meter):
__mapper_args__ = {'polymorphic_identity': 'main_meter'}
trading_point_name  = sa.Column(sa.Unicode(255), nullable=True,
unique=True)
#and so forth

class CheckMeter(Meter):
__mapper_args__ = {'polymorphic_identity': 'check_meter'}
#etc

Details:
Sqlalchemy 7.3
Sqlite db backend
Python2.5

Best regards,
Damian

-- 
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] Declarative Mapping vs Classic Mapping

2011-10-17 Thread Manav Goel
My question is regarding sqlalchemy version 0.7.2.

Are there any limitations in using declarative or classic mapping
while using sqlalchemy?

My main concern is there any limitation of declarative mapping which
can put me in some situation where I am stuck with the tables it will
create?

Also what about table schema changes, If I want to add a column or
remove a column from table I simply add or remove that attribute in
declarative class?

I have completed my table design and thinking to create database in
one go using declarative mapping.

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



Re: [sqlalchemy] Determine column properties created via declarative mixins

2011-10-17 Thread Michael Bayer

On Oct 17, 2011, at 5:40 AM, Robert Forkel wrote:

 Hi all,
 Using sqlalchemy 0.7.2 I created a couple of mixin classes (say Mixin)
 to share columns declarations between model classes (say A and B).
 Sometimes I have to create instances of type B initialized with the
 values of an existing object of type A for the columns declared by
 Mixin. I'd like to make this code extensible with respect to the
 columns declared in Mixin, i.e. adding new columns to Mixin should
 require updating this code.
 Is there a way to find the names of column properties contributed by a
 Mixin?
 (I tried with checking Mixin.__dict__ for items of type
 sqlalchemy.schema.Column, but this doesn't give foreign keys declared
 via @declared_attr)
 best regards
 robert

the mixin is pretty much what you see there, a Python class with some 
attributes.  @declared_attr doesn't do anything except allow the function to 
act like an attribute at the class level (it's just one line), and also is a 
marker object recognized by Declarative.   So if you wanted to see what a 
certain attribute had, you'd call it, that is, instead of looking in __dict__, 
you'd say:

for attr in dir(MyMixin):
value = getattr(MyMixin, attr)
# inspect value


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



Re: [sqlalchemy] History meta and unique issue

2011-10-17 Thread Michael Bayer
ah the example has a bug, you're hitting a second part of the code there where 
it fetches columns that are placed on a single table child class that are moved 
up to the parent.   Committing this now, here's a patch:

diff -r 653ae7f17379 examples/versioning/history_meta.py
--- a/examples/versioning/history_meta.py   Mon Oct 17 13:14:04 2011 -0400
+++ b/examples/versioning/history_meta.py   Mon Oct 17 13:19:41 2011 -0400
@@ -60,6 +60,7 @@
 for column in local_mapper.local_table.c:
 if column.key not in super_history_mapper.local_table.c:
 col = column.copy()
+col.unique = False
 super_history_mapper.local_table.append_column(col)
 table = None
 


this is rd87af238de36


On Oct 17, 2011, at 12:56 PM, Damian wrote:

 Hello!
 
 I've run into an odd error whilst using the history meta.  I've got a
 class which has two sub classes which define some additional columns.
 The MainMeter class has a unique constraint on one of the colums.
 When I have the history_meta create my history tables, the
 trading_point_name column retains its unique constraint despite there
 being a col.unique = False in the history meta which should disable
 it.  I can't quite figure out why this is happening.  Any hints would
 be appreciated!
 
 class Meter(Base, BaseMixin):
__metaclass__ = VersionedMeta
__tablename__ = meters
 
id = sa.Column(sa.Integer, primary_key=True)
type = sa.Column(sa.Enum('main_meter', 'check_meter'))
# and so forth
 
 class MainMeter(Meter):
__mapper_args__ = {'polymorphic_identity': 'main_meter'}
trading_point_name  = sa.Column(sa.Unicode(255), nullable=True,
 unique=True)
#and so forth
 
 class CheckMeter(Meter):
__mapper_args__ = {'polymorphic_identity': 'check_meter'}
#etc
 
 Details:
 Sqlalchemy 7.3
 Sqlite db backend
 Python2.5
 
 Best regards,
 Damian
 
 -- 
 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.
 

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



Re: [sqlalchemy] Declarative Mapping vs Classic Mapping

2011-10-17 Thread Michael Bayer

On Oct 17, 2011, at 1:05 PM, Manav Goel wrote:

 My question is regarding sqlalchemy version 0.7.2.
 
 Are there any limitations in using declarative or classic mapping
 while using sqlalchemy?

there's not, a declarative mapping is nothing more than a small organizing 
layer on top of the classical system of class + Table + mapper() - all three 
elements are used in the same way.

 
 My main concern is there any limitation of declarative mapping which
 can put me in some situation where I am stuck with the tables it will
 create?

Declarative allows the full range of table specification that plain Table() 
allows, and additionally you can use the Table construct directly with any 
declarative class (I use this style in my current project) as demonstrated at 
http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#using-a-hybrid-approach-with-table
 .


 
 Also what about table schema changes, If I want to add a column or
 remove a column from table I simply add or remove that attribute in
 declarative class?

That's a different story.   SQLAlchemy's table metadata is only an in-python 
document describing the structure of an existing schema in a remote database.   
While table metadata has the ability to emit CREATE statements to this remote 
database, that's as far as it goes.   When using relational databases, adding 
columns means that an ALTER statement must be emitted on the target database.   
You'd need to emit these ALTER commands yourself, if you'd like an existing 
schema to gain new columns that you've added to your SQLalchemy model.  Or if 
you're in development, you can alternatively (and IMHO this is much easier, 
assuming you're working only with development databases) drop the whole 
database and recreate it, where the new columns will be present.

There is also the approach of using a tool like SQLAlchemy-Migrate which gives 
you a place to define table alterations, and does the work of composing the 
ALTER statements in a semi-automated fashion.

Regardless, the choice of declarative versus classical has no impact here, save 
for the fact that SQLAlchemy-Migrate works a little more clearly when you give 
it Table constructs to work with, rather than copies of your declared classes.  
 When I've used migrate in the past, it's entirely unnecessary to copy the full 
table definition as its docs suggest, I tend to just use Table(mytable, 
metadata, autoload=True) to get at the current Table object before applying 
alterations, so the usage of declarative has no impact.

 
 I have completed my table design and thinking to create database in
 one go using declarative mapping.

should be fine it's not that much of a commitment !

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



Re: [sqlalchemy] Declarative Mapping vs Classic Mapping

2011-10-17 Thread Manav Goel
Thanks for the quick reply.

One question here, suppose I add column using Alter Table command and then in 
class declaration the attribute. Will it see the newly added column then or not?

Concern is not issuing ALTER command by hand but is the class can see the newly 
added column.

Regards,
Manav Goel
On 17-Oct-2011, at 11:06 PM, Michael Bayer wrote:

 
 On Oct 17, 2011, at 1:05 PM, Manav Goel wrote:
 
 My question is regarding sqlalchemy version 0.7.2.
 
 Are there any limitations in using declarative or classic mapping
 while using sqlalchemy?
 
 there's not, a declarative mapping is nothing more than a small organizing 
 layer on top of the classical system of class + Table + mapper() - all three 
 elements are used in the same way.
 
 
 My main concern is there any limitation of declarative mapping which
 can put me in some situation where I am stuck with the tables it will
 create?
 
 Declarative allows the full range of table specification that plain Table() 
 allows, and additionally you can use the Table construct directly with any 
 declarative class (I use this style in my current project) as demonstrated at 
 http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#using-a-hybrid-approach-with-table
  .
 
 
 
 Also what about table schema changes, If I want to add a column or
 remove a column from table I simply add or remove that attribute in
 declarative class?
 
 That's a different story.   SQLAlchemy's table metadata is only an in-python 
 document describing the structure of an existing schema in a remote database. 
   While table metadata has the ability to emit CREATE statements to this 
 remote database, that's as far as it goes.   When using relational databases, 
 adding columns means that an ALTER statement must be emitted on the target 
 database.   You'd need to emit these ALTER commands yourself, if you'd like 
 an existing schema to gain new columns that you've added to your SQLalchemy 
 model.  Or if you're in development, you can alternatively (and IMHO this is 
 much easier, assuming you're working only with development databases) drop 
 the whole database and recreate it, where the new columns will be present.
 
 There is also the approach of using a tool like SQLAlchemy-Migrate which 
 gives you a place to define table alterations, and does the work of composing 
 the ALTER statements in a semi-automated fashion.
 
 Regardless, the choice of declarative versus classical has no impact here, 
 save for the fact that SQLAlchemy-Migrate works a little more clearly when 
 you give it Table constructs to work with, rather than copies of your 
 declared classes.   When I've used migrate in the past, it's entirely 
 unnecessary to copy the full table definition as its docs suggest, I tend to 
 just use Table(mytable, metadata, autoload=True) to get at the current 
 Table object before applying alterations, so the usage of declarative has no 
 impact.
 
 
 I have completed my table design and thinking to create database in
 one go using declarative mapping.
 
 should be fine it's not that much of a commitment !
 
 -- 
 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.
 

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



Re: [sqlalchemy] Declarative Mapping vs Classic Mapping

2011-10-17 Thread Michael Bayer
The usual development model encouraged by SQLAlchemy is that class and table 
definitions are a fixed element of your program, declared at the module level.  
  So typically, adding new columns means you're modifying the source code of 
your app, then rerunning.

That said, if you add a column to a declarative model at runtime, the 
Declarative metaclass does intercept this and will invoke add_column() on the 
Table as well as add_property() on the mapper.Existing objects created 
against the mapper will have undefined behavior regarding this new attribute, 
however, which again speaks to the practice that an app should really be run 
with against a fixed schema - the additive modification supported by Table 
and mapper() still assumes the application is setting itself up when these 
methods are called, and that the program hasn't already been running for some 
time.



On Oct 17, 2011, at 1:47 PM, Manav Goel wrote:

 Thanks for the quick reply.
 
 One question here, suppose I add column using Alter Table command and then in 
 class declaration the attribute. Will it see the newly added column then or 
 not?
 
 Concern is not issuing ALTER command by hand but is the class can see the 
 newly added column.
 
 Regards,
 Manav Goel
 On 17-Oct-2011, at 11:06 PM, Michael Bayer wrote:
 
 
 On Oct 17, 2011, at 1:05 PM, Manav Goel wrote:
 
 My question is regarding sqlalchemy version 0.7.2.
 
 Are there any limitations in using declarative or classic mapping
 while using sqlalchemy?
 
 there's not, a declarative mapping is nothing more than a small organizing 
 layer on top of the classical system of class + Table + mapper() - all three 
 elements are used in the same way.
 
 
 My main concern is there any limitation of declarative mapping which
 can put me in some situation where I am stuck with the tables it will
 create?
 
 Declarative allows the full range of table specification that plain Table() 
 allows, and additionally you can use the Table construct directly with any 
 declarative class (I use this style in my current project) as demonstrated 
 at 
 http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#using-a-hybrid-approach-with-table
  .
 
 
 
 Also what about table schema changes, If I want to add a column or
 remove a column from table I simply add or remove that attribute in
 declarative class?
 
 That's a different story.   SQLAlchemy's table metadata is only an in-python 
 document describing the structure of an existing schema in a remote 
 database.   While table metadata has the ability to emit CREATE statements 
 to this remote database, that's as far as it goes.   When using relational 
 databases, adding columns means that an ALTER statement must be emitted on 
 the target database.   You'd need to emit these ALTER commands yourself, if 
 you'd like an existing schema to gain new columns that you've added to your 
 SQLalchemy model.  Or if you're in development, you can alternatively (and 
 IMHO this is much easier, assuming you're working only with development 
 databases) drop the whole database and recreate it, where the new columns 
 will be present.
 
 There is also the approach of using a tool like SQLAlchemy-Migrate which 
 gives you a place to define table alterations, and does the work of 
 composing the ALTER statements in a semi-automated fashion.
 
 Regardless, the choice of declarative versus classical has no impact here, 
 save for the fact that SQLAlchemy-Migrate works a little more clearly when 
 you give it Table constructs to work with, rather than copies of your 
 declared classes.   When I've used migrate in the past, it's entirely 
 unnecessary to copy the full table definition as its docs suggest, I tend to 
 just use Table(mytable, metadata, autoload=True) to get at the current 
 Table object before applying alterations, so the usage of declarative has no 
 impact.
 
 
 I have completed my table design and thinking to create database in
 one go using declarative mapping.
 
 should be fine it's not that much of a commitment !
 
 -- 
 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.
 
 
 -- 
 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.
 

-- 
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] INNER JOIN inside an OUTER JOIN

2011-10-17 Thread Phil Vandry
Hello,

I have a schema that includes these relationships:

class Airport(Base):
...

class Runway(Base):
...
airport = relationship(Airport, backref=backref(runways, 
collection_class=set), lazy=joined, innerjoin=True)
...

class FlightEvent(Base):
...
runway = relationship(Runway, lazy=joined)
...

- Whenever I fetch FlightEvents, I want to automatically fetch the
runways that may be referenced by the event, hence lazy=joined in
the runway = relationship. This relationship is an outer join because
an event may or may not reference a runway.

- Whenever I fetch Runways, I want to automatically fetch the Airport
where those runways are located, so another lazy=joined. This one is
an inner join because a runway is guaranteed to have an associated
airport.

The generated SQL contains this (formatting added):

FROM flight_events
  LEFT OUTER JOIN world.runways AS runways_1
ON runways_1.runway_id = flight_events.runway_id
  INNER JOIN world.airports AS airports_1
ON airports_1.airport_id = runways_1.airport_id

Unfortunately this doesn't work. Due to the INNER JOIN to airports, only
events which reference runways (which in turn reference airports) are
returned.

The only way I know to make this work is for the INNER JOIN to be
contained inside the RHS of the OUTER JOIN (where it logically belongs).
If the SQL fragment above is replace with the following, it works:

FROM flight_events
  LEFT OUTER JOIN (
world.runways AS runways_1
  INNER JOIN world.airports AS airports_1
ON airports_1.airport_id = runways_1.airport_id
  )
ON runways_1.runway_id = flight_events.runway_id

Is there a way to convince SQLAlchemy to generate this kind of SQL?
If so, I was not able to find how. It seems that the AST given as
input to the SQL compiler has the joins defined flat, not
hierarchically (i.e. the INNER JOIN of runways and airports is not an
AST node under the RHS of the toplevel OUTER JOIN).

Using SQLAlchemy 0.6.3 (from Debian stable... yeah, I know Debian is
behind the current version) with MySQL 5.1.49.

-Phil

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



Re: [sqlalchemy] INNER JOIN inside an OUTER JOIN

2011-10-17 Thread Michael Bayer

On Oct 17, 2011, at 3:28 PM, Phil Vandry wrote:

 
 - Whenever I fetch FlightEvents, I want to automatically fetch the
 runways that may be referenced by the event, hence lazy=joined in
 the runway = relationship. This relationship is an outer join because
 an event may or may not reference a runway.
 
 - Whenever I fetch Runways, I want to automatically fetch the Airport
 where those runways are located, so another lazy=joined. This one is
 an inner join because a runway is guaranteed to have an associated
 airport.
 
 The generated SQL contains this (formatting added):
 
 FROM flight_events
  LEFT OUTER JOIN world.runways AS runways_1
ON runways_1.runway_id = flight_events.runway_id
  INNER JOIN world.airports AS airports_1
ON airports_1.airport_id = runways_1.airport_id
 
 Unfortunately this doesn't work. Due to the INNER JOIN to airports, only
 events which reference runways (which in turn reference airports) are
 returned.

This is because you're using an ancient version of SQLAlchemy that was one of 
the first to ever feature the innerjoin flag.Was fixed in 0.6.6.I'd 
strongly advise, not just for SQLAlchemy but for Python overall, to use pip 
to install Python libraries instead of relying upon distribution installs, 
Python libraries are developed a lot more quickly than linux distros and you'll 
have a lot less headache.  Especially if starting a new project with 
SQLAlchemy, your app will run a lot faster with 0.7, be easier to develop, and 
be easier to upgrade as new releases come out.

Post 0.6.5 the full chain of eager loaders detects the outer join up the chain 
and converts them all to outer join.   Here's an example:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import *
from sqlalchemy.orm import *

Base = declarative_base()

class Airport(Base):
__tablename__ = 'airport'
id = Column(Integer, primary_key=True)

class Runway(Base):
__tablename__ = 'runway'
id = Column(Integer, primary_key=True)
airport_id = Column(Integer, ForeignKey('airport.id'))
airport = relationship(Airport, 
backref=backref(runways, collection_class=set), 
lazy=joined, innerjoin=True)

class FlightEvent(Base):
__tablename__ = 'flightevent'
id = Column(Integer, primary_key=True)
runway_id = Column(Integer, ForeignKey('runway.id'))
runway = relationship(Runway, lazy=joined)

s = Session()
print s.query(FlightEvent)

output:

SELECT flightevent.id AS flightevent_id, flightevent.runway_id AS 
flightevent_runway_id, airport_1.id AS airport_1_id, runway_1.id AS 
runway_1_id, runway_1.airport_id AS runway_1_airport_id 
FROM flightevent LEFT OUTER JOIN runway AS runway_1 ON runway_1.id = 
flightevent.runway_id LEFT OUTER JOIN airport AS airport_1 ON airport_1.id = 
runway_1.airport_id

its only if you have no outer joins in the preceding chain do you get the 
INNER join:

SELECT runway.id AS runway_id, runway.airport_id AS runway_airport_id, 
airport_1.id AS airport_1_id 
FROM runway JOIN airport AS airport_1 ON airport_1.id = runway.airport_id

so the correct results are returned.  However, OUTER JOIN does not perform as 
well as INNER JOIN, which is the real problem here.

 
 The only way I know to make this work is for the INNER JOIN to be
 contained inside the RHS of the OUTER JOIN (where it logically belongs).
 If the SQL fragment above is replace with the following, it works:
 
 FROM flight_events
  LEFT OUTER JOIN (
world.runways AS runways_1
  INNER JOIN world.airports AS airports_1
ON airports_1.airport_id = runways_1.airport_id
  )
ON runways_1.runway_id = flight_events.runway_id
 
 Is there a way to convince SQLAlchemy to generate this kind of SQL?

absolutely, but not using joinedload() or lazy=joined, read on...

 If so, I was not able to find how. It seems that the AST given as
 input to the SQL compiler has the joins defined flat, not
 hierarchically (i.e. the INNER JOIN of runways and airports is not an
 AST node under the RHS of the toplevel OUTER JOIN).


So assuming you want the performance increase potentially afforded by x outer 
join (y join z), as opposed to just the right results, you need to specify the 
joins yourself.   SQLAlchemy can't invoke x JOIN (y JOIN z) across the board 
because it is not supported by all backends, specifically sqlite:

sqlite create table foo(id integer);
sqlite create table bar(id integer);
sqlite create table bat(id integer);
sqlite select * from foo left outer join (bar join bat on bar.id=bat.id) on 
foo.id=bat.id;
Error: no such column: bat.id

It also would probably fail against an Oracle 8 backend, as we need to jump 
through some hoops to convert out all the JOINs to = and x=y(+) operators.  
 The ORM's construction of the chain of joins does so above the level of SQL 
rendering, so for the moment it unwraps it outwards the way it does for full 
cross-compatibility.Having it nest the joins is an improvement we've 

Re: [sqlalchemy] Determine column properties created via declarative mixins

2011-10-17 Thread Robert Forkel
Hi Michael,
going down the way you pointed I ran into what might be a small bug in
sqlalchemy: Trying to print out a RelationshipProperty I get

project_leader Traceback (most recent call last):
  File stdin, line 3, in module
  File 
/home/rforkel/projects/gulpenv/lib/python2.6/site-packages/sqlalchemy/orm/properties.py,
line 724, in __str__
return str(self.parent.class_.__name__) + . + self.key
AttributeError: 'RelationshipProperty' object has no attribute 'parent'
 import sqlalchemy
 sqlalchemy.__version__
'0.7.2'

Anyway, your hint solved my problem, thanx!
regards
robert

On Mon, Oct 17, 2011 at 7:10 PM, Michael Bayer mike...@zzzcomputing.com wrote:

 On Oct 17, 2011, at 5:40 AM, Robert Forkel wrote:

 Hi all,
 Using sqlalchemy 0.7.2 I created a couple of mixin classes (say Mixin)
 to share columns declarations between model classes (say A and B).
 Sometimes I have to create instances of type B initialized with the
 values of an existing object of type A for the columns declared by
 Mixin. I'd like to make this code extensible with respect to the
 columns declared in Mixin, i.e. adding new columns to Mixin should
 require updating this code.
 Is there a way to find the names of column properties contributed by a
 Mixin?
 (I tried with checking Mixin.__dict__ for items of type
 sqlalchemy.schema.Column, but this doesn't give foreign keys declared
 via @declared_attr)
 best regards
 robert

 the mixin is pretty much what you see there, a Python class with some 
 attributes.  @declared_attr doesn't do anything except allow the function to 
 act like an attribute at the class level (it's just one line), and also is a 
 marker object recognized by Declarative.   So if you wanted to see what a 
 certain attribute had, you'd call it, that is, instead of looking in 
 __dict__, you'd say:

 for attr in dir(MyMixin):
    value = getattr(MyMixin, attr)
    # inspect value


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



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