Re: [sqlalchemy] SQLAlchemy 0.7 beta 1 released

2011-02-15 Thread Wichert Akkerman

Hi Mike,

I grabbed SQLAlchemy from pypi when it was still there so I could do a 
quick test with my current projects (yay for buildout with version 
pinning). I'm happy to be able to report that the upgrade was seemless, 
and all my tests were passing with 0.7b1.


Wichert.


On 2/13/11 01:51 , Michael Bayer wrote:

Hey list -

The first beta release of SQLAlchemy 0.7 is available for download.

0.7 is the latest iteration of our yearly cycle where each new version brings 
lots of new features and enhancements, refines APIs and patterns while 
deprecating others, and removes old APIs that have been deprecated for at least 
one major revision series (i.e. throughout 0.6).

The initial push in 0.7 focuses on a reorganization of the event system.  Over the years we've 
accumulated various Extension classes like MapperExtension, SessionExtension, as well as core 
constructs like ConnectionProxy, PoolListener, and then a bunch of other more surreptitious systems like 
class instrumentation events, schema association events that were not fully public.   In 0.7, everything 
resembling an event is now available through a single unified API called sqlalchemy.event.   It's 
a single import of a single function listen() that serves as the gateway to associating user-defined 
callables with all events throughout the core and ORM.   All the Extension classes and similar still remain 
for the time being, their underlying implementations now routing through event.

At the same time as event was going on, I found myself using Ants Aasma's derived attributes example like crazy in my day job.   This system allows the construction of Python 
class attributes that produce a Python result at the object level and a SQL expression at the class level, building upon the paradigm already present in a SQLAlchemy mapped class.I enhanced the 
example in 0.6 such that special cases where the two situations weren't completely symmetrical could be implemented using some additional directives.It became apparent that the extremely simple 
idea in derived attributes was really a superset of synonym, comparable_property, and to some degree composite().So in 0.7 we've 
mainstreamed derived attributes as sqlalchemy.ext.hybrid.   The synonym, comparable_property, and composite  APIs have been 
refactored such that their usage is mostly the same as it was previously, but their underlying implementation uses approximately the sam

e concept as ext.hybrid, and their implementations have been moved out of the core ORM 
modules, allowing us to simplify some things internally.  The documentation now 
encourages the usage of sqlalchemy.ext.hybrid for customized attributes that 
produce new expressions derived from the class and also function at the instance level, 
in lieu of synonym and comparable_property.


The third story of 0.7 is that we did a lot more work on speed, which includes that we've come up with a viable replacement for 
the mutable behavior of certain types, mainly PickleType, composite(), and postgresql.ARRAY.   The 
mutable flag on these types is now turned off by default - while the old system of detecting in place 
mutation was fine for small jobs, it completely cripples the application as it begins to handle higher volumes of data, as 
it relied upon scanning all mutable objects in the Session in order to detect changes in these attributes.  The 
autoflush operation basically becomes O(N) instead of O(1) the minute an object with a mutable attribute is placed in 
the session.

A new system which allows one to construct on change events specific to the kind of data structure being stored in a 
scalar value is added in sqlalchemy.ext.mutable.   This is a brand new system that hopefully should grow as we move 
through 0.7 to support various Python structures out of the box, like dicts, lists and composites of those.   The turning off of 
mutable is likely the one most major hard change in the system - if your application relies upon in-place 
mutation of PickleType or postgresql.ARRAY, you'd need to turn that flag on until your app can be altered to use the new system.  
 If your application relies upon in-place mutability of composite() (I'm assuming this is a very rare scenario, composite() isn't 
that common in the first place), the new system has to be used for that, which requires a little bit of modification to the 
user-defined composite class.   Heavy users of mutable should notice an immediate effect by switching off of the old 
system.

A long list of everything to be aware of is ready for viewing at 
http://www.sqlalchemy.org/trac/wiki/07Migration .While there are many 
changes, it is my impression that the vast majority of applications coded 
against 0.6 will run on 0.7 without modification,   Very few changes are 
backwards incompatible, and of those fifteen changes which are, most are things 
that were never documented or were essentially silent failures.

The purpose of the beta is to get community 

Re: [sqlalchemy] Re: The right way to clear database of content?

2011-02-15 Thread Arve Knudsen
Thank you GHZ, it did work! Wondering about one thing though; the recipe in
the documentation iterates over the tables in reverse sorted order, like so:

for table in reversed(meta.sorted_tables)

Do you know what this would be good for (since your code does not care about
the table order)?

Arve

On Mon, Feb 14, 2011 at 2:51 PM, GHZ geraint.willi...@gmail.com wrote:

 maybe it needs to be in a transaction:


 con = engine.connect()

 trans = con.begin()

 for name, table in meta.tables.items():

print table.delete()
con.execute(table.delete())

 trans.commit()



 On Feb 14, 1:29 pm, Arve Knudsen arve.knud...@gmail.com wrote:
  Hi
 
  What's the right way to clear a database all of content, but keep the
  schema? I tried the method of deleting all tables athttp://
 www.sqlalchemy.org/docs/05/metadata.html#reflecting-all-tables...,
  but content still remains. I couldn't find any documentation on
 Table.delete
  either, for that matter. Maybe I'm missing something...
 
  Thanks,
  Arve

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



[sqlalchemy] Re: The right way to clear database of content?

2011-02-15 Thread GHZ
I the order is required for Foreign Key relationships. i.e. to make
sure the children are deleted before the parents.

So the for table in reversed(meta.sorted_tables) example is the more
correct way to delete all data.



On Feb 15, 1:29 pm, Arve Knudsen arve.knud...@gmail.com wrote:
 Thank you GHZ, it did work! Wondering about one thing though; the recipe in
 the documentation iterates over the tables in reverse sorted order, like so:

 for table in reversed(meta.sorted_tables)

 Do you know what this would be good for (since your code does not care about
 the table order)?

 Arve







 On Mon, Feb 14, 2011 at 2:51 PM, GHZ geraint.willi...@gmail.com wrote:
  maybe it needs to be in a transaction:

  con = engine.connect()

  trans = con.begin()

  for name, table in meta.tables.items():

     print table.delete()
     con.execute(table.delete())

  trans.commit()

  On Feb 14, 1:29 pm, Arve Knudsen arve.knud...@gmail.com wrote:
   Hi

   What's the right way to clear a database all of content, but keep the
   schema? I tried the method of deleting all tables athttp://
 www.sqlalchemy.org/docs/05/metadata.html#reflecting-all-tables...,
   but content still remains. I couldn't find any documentation on
  Table.delete
   either, for that matter. Maybe I'm missing something...

   Thanks,
   Arve

  --
  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] Re: The right way to clear database of content?

2011-02-15 Thread Arve Knudsen
Aha, thanks again! :)

Arve

On Tue, Feb 15, 2011 at 1:55 PM, GHZ geraint.willi...@gmail.com wrote:

 I the order is required for Foreign Key relationships. i.e. to make
 sure the children are deleted before the parents.

 So the for table in reversed(meta.sorted_tables) example is the more
 correct way to delete all data.



 On Feb 15, 1:29 pm, Arve Knudsen arve.knud...@gmail.com wrote:
  Thank you GHZ, it did work! Wondering about one thing though; the recipe
 in
  the documentation iterates over the tables in reverse sorted order, like
 so:
 
  for table in reversed(meta.sorted_tables)
 
  Do you know what this would be good for (since your code does not care
 about
  the table order)?
 
  Arve
 
 
 
 
 
 
 
  On Mon, Feb 14, 2011 at 2:51 PM, GHZ geraint.willi...@gmail.com wrote:
   maybe it needs to be in a transaction:
 
   con = engine.connect()
 
   trans = con.begin()
 
   for name, table in meta.tables.items():
 
  print table.delete()
  con.execute(table.delete())
 
   trans.commit()
 
   On Feb 14, 1:29 pm, Arve Knudsen arve.knud...@gmail.com wrote:
Hi
 
What's the right way to clear a database all of content, but keep the
schema? I tried the method of deleting all tables athttp://
  www.sqlalchemy.org/docs/05/metadata.html#reflecting-all-tables...,
but content still remains. I couldn't find any documentation on
   Table.delete
either, for that matter. Maybe I'm missing something...
 
Thanks,
Arve
 
   --
   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+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Pypi release policy

2011-02-15 Thread Eric Lemoine
On Monday, February 14, 2011, Michael Bayer mike...@zzzcomputing.com wrote:

 On Feb 14, 2011, at 12:11 PM, Tarek Ziadé wrote:

 On Mon, Feb 14, 2011 at 6:00 PM, Michael Bayer mike...@zzzcomputing.com 
 wrote:

 On Feb 14, 2011, at 5:53 AM, Tarek Ziadé wrote:

 On Mon, Feb 14, 2011 at 11:44 AM, Wichert Akkerman wich...@wiggy.net 
 wrote:
 ..

 you don't release at pypi a version that breaks the latest stable.  or
 if you do, you check the hidden attribute on that release, to avoid
 this problem with installers

 SQLAlchemy 0.7b1 is hidden. The hidden flag only hides it from humans
 though, not from setuptools.

 oh true...I forgot it's not hidden in the simple index :/

 OK so you're the expert - how does one release a beta on pypi without 
 crashing everyone's stable install ?   should i just stick to sourceforge 
 until final release ?

 Unfortunately, Setuptools will pick the latest version and won't care
 about beta tags (zc.buildout has such feature -- prefer-final, and
 Distutils2 too)

 So I guess the best way with the current eco-system is to avoid
 pushing any unstable release to PyPI

 or... if you have the time to do so, push a new 0.7 beta that makes
 sure people that run on the latest 0.6 can run it -- with deprecation
 warnings all over the place :)

 I'll pull it off of Pypi.

 We definitely do push for as much backwards compat as possible,  but the 
 release does remove / hard change things that were raising warnings 
 throughout 0.6, as well as lots of apps rely upon undocumented behaviors 
 which may have changed, so its inevitable that some apps will need adjustment.

 But the code itself should not be considered as bug-free as a stable 
 release so in any case its not appropriate to push it into installations 
 without explicit consent.


But aren't apps supposed to use =0.6.99 to avoid backward compats
issues? Apps that don't will also break when 0.7 final is on pypi.

-- 
Eric Lemoine

Camptocamp France SAS
Savoie Technolac, BP 352
73377 Le Bourget du Lac, Cedex

Tel : 00 33 4 79 44 44 96
Mail : eric.lemo...@camptocamp.com
http://www.camptocamp.com

-- 
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] Pypi release policy

2011-02-15 Thread Tarek Ziadé
On Tue, Feb 15, 2011 at 3:27 PM, Eric Lemoine
eric.lemo...@camptocamp.com wrote
..

 But aren't apps supposed to use =0.6.99 to avoid backward compats
 issues? Apps that don't will also break when 0.7 final is on pypi.

There are different things here:

1/ PyPI allows projects to publish any release, and easy_install will
pick the latest one, whether it's a final (==stable) or not. You can
publish your trunk if you want.

2/ An application that defines a dependency can define it in different flavors:

a - Give me the latest release that was made available at PyPI
b - Give me the latest release from the 0.6.x series,   it can use a
0.7 or 0.6.99
c - Give me version XX   --- best practice once in production


For applications that are using 2.a, the interpretation of most people
is that the latest release at PyPI they are depending on is not a
development release. If they want a development release, they do it
explicitly in their environment to leave on the edge.

3/ a user types easy_install SQLAlchemy and wants the latest stable

So, yeah, when 0.7.1 final will be out, some apps will break -- but
they've been warned and they can choose to change their code or pin
their dependency to the 0.6.x series. But right now, it's a
development release that has been published for feedback as opposed to
a final release.

The less disruptive process (until distutils2 is available) in that
case is to let people opt in to be beta testers, and let SQLAlchemy
means latest stable, whether it's called by easy_install
SQLAlchemy or in the install_requires option in setuptools.


Cheers
Tarek

-- 
Tarek Ziadé | http://ziade.org

-- 
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] Hybrid Property and func.sum()

2011-02-15 Thread Florian Mueller
Hey

Thanks for the answers. I have a few follow-ups if you don't mind.

Hi

 I'm confronted with the following situation:

 I have two entities:

 Account 1:n AccountEntry

 AccountEntry has a column (and property) 'amount'.

 Now I'd like to implement a @hybrid_property.expression 'balance' on
 Account which uses func.sum(AccountEntry.amount) to calculate the account's
 balance.

 When I do:

 @balance.expression
 def balance(cls):
 return func.sum(AccountEntry.amount)

 sqlalchemy.exc.ProgrammingError: (ProgrammingError) (b'ERROR', b'42803',
 b'aggregates not allowed in WHERE clause')

 which is ok, since you have to have a sub-select like

 select * from accounts as a where (select sum(ae.amount) as balance from
 account_entries as ae where ae.account_id = a.id)  0

 Now my question: How to achieve this using @hybrid_property.expression?
 Which query fragment I have to return?


 you can return the subquery:

 @balance.expression
 def balance(cls):
 return
 Session().query(func.sum(AccountEntry.amount)).filter(AccountEntry.account_id==
 cls.id).as_scalar()


I finally managed the case doing this.

@hybrid_property
def balance(self):
return db.session.query(AccountEntry.account_id,
func.sum(AccountEntry.amount).label('b')).group_by(AccountEntry.account_id).having(AccountEntry.account_id==
self.id).one().b

@balance.expression
def balance(cls):
return
Session().query(func.sum(AccountEntry.amount)).group_by(AccountEntry.account_id).having(AccountEntry.account_id==
cls.id).as_scalar()



 note I'm using a do-nothing Session() there since we're generating a SQL
 construct that will be embedded into another.

 Usually when I work with aggregates like that I like to keep things more
 explicit.  Suppose your original Account.balance descriptor:

 balances = session.query(AccountEntry.account_id,
 Account.balance.label('balance')).group_by(AccountEntry.account_id).subquery()

 accounts = session.query(Account).join(balances,
 Account.entries).filter(balances.c.balance  0)

 i.e. the hybrid represents a particular type of expression, but it is
 context-dependent.   Its a typical practicality beats purity type of
 decision (like the rest of SQLA...)


Well we're just trying out what SQLA is capable of at the moment and trying
to build up a proper api. We run into a similar issue then:

We have an entity Party which has n Language through PartyLanguage. On
PartyLanguage there is a field called order. The one with the lowest
order is the parties primary language. Now it would be very pretty to be
able to do those things:

1. someparty.primary_language = Language('en')
2. assert someparty.primary_language == Language('en')
3. someparty.languages.append(Language('de'))
4. session.query(Party).filter(Party.primary_language=Language('en')).all()

don't you think so? But we enquire a whole lot of problems. We managed to do
most things except for 4. We implemented @primary_language.expression like
this:

@primary_language.expression
def _primary_language_expression(cls):
return Session().query(Language.iso)\
.join(PartyLanguage)\
.order_by(PartyLanguage.order)\
.group_by(PartyLanguage.party_id, Language.iso,
PartyLanguage.order)\
.having(PartyLanguage.party_id==cls.id)\
.limit(1)\
.as_scalar()

This works so far but there is still the need to use it in a query like
this:

language = Language('en')
session.query(Party).filter(Party.primary_language=language.iso).all()

I guess it's all about the compare behavior of the expression returned
by _primary_language_expression. It includes Language as a type into the
query, which leads to a not supported type error.

So are we doing it all wrong, is SQLA not ment to write those kind of API's?
Is it possible to achieve what we like to do?

Best regards,
Florian

-- 
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] Troubles with LEFT OUTER JOIN

2011-02-15 Thread Michael Hipp
Can someone help me understand why I can't seem to do a simple left outer join 
between these two tables:


q = self.session.query(Car, Invoice.id_)
q = q.outerjoin(Car, Invoice)

sqlalchemy.exc.ArgumentError: Can't find any foreign key relationships between 
'cars' and 'cars'.


Thanks,
Michael
---
class Car(Base):
__tablename__ = 'cars'
id_ = Column(Integer, primary_key=True)

class Invoice(Base):
__tablename__ = 'invoices'
id_ = Column(Integer, primary_key=True)
car_id = Column(Integer, ForeignKey('cars.id_'))
car = relationship(Car, backref=backref('invoices', order_by=id_),
   primaryjoin=Invoice.car_id==Car.id_)

--
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] Hybrid Property and func.sum()

2011-02-15 Thread Michael Bayer

On Feb 15, 2011, at 12:02 PM, Florian Mueller wrote:

 Hey
 
 Thanks for the answers. I have a few follow-ups if you don't mind.
 
 Hi
 
 I'm confronted with the following situation:
 
 I have two entities:
 
 Account 1:n AccountEntry
 
 AccountEntry has a column (and property) 'amount'.
 
 Now I'd like to implement a @hybrid_property.expression 'balance' on Account 
 which uses func.sum(AccountEntry.amount) to calculate the account's balance.
 
 When I do:
 
 @balance.expression
 def balance(cls):
 return func.sum(AccountEntry.amount)
 
 sqlalchemy.exc.ProgrammingError: (ProgrammingError) (b'ERROR', b'42803', 
 b'aggregates not allowed in WHERE clause')
 
 which is ok, since you have to have a sub-select like
 
 select * from accounts as a where (select sum(ae.amount) as balance from 
 account_entries as ae where ae.account_id = a.id)  0
 
 Now my question: How to achieve this using @hybrid_property.expression? 
 Which query fragment I have to return?
 
 you can return the subquery:
 
   @balance.expression
   def balance(cls):
   return 
 Session().query(func.sum(AccountEntry.amount)).filter(AccountEntry.account_id==cls.id).as_scalar()
 
 I finally managed the case doing this.
 
 @hybrid_property
 def balance(self):
 return db.session.query(AccountEntry.account_id, 
 func.sum(AccountEntry.amount).label('b')).group_by(AccountEntry.account_id).having(AccountEntry.account_id==self.id).one().b

for 'self' why not use python and the collection: sum(a.amount for a in 
self.entries) ?


 
 @balance.expression
 def balance(cls):
 return 
 Session().query(func.sum(AccountEntry.amount)).group_by(AccountEntry.account_id).having(AccountEntry.account_id==cls.id).as_scalar()
 
 
 
 note I'm using a do-nothing Session() there since we're generating a SQL 
 construct that will be embedded into another.
 
 Usually when I work with aggregates like that I like to keep things more 
 explicit.  Suppose your original Account.balance descriptor:
 
   balances = session.query(AccountEntry.account_id, 
 Account.balance.label('balance')).group_by(AccountEntry.account_id).subquery()
 
   accounts = session.query(Account).join(balances, 
 Account.entries).filter(balances.c.balance  0)
  
 i.e. the hybrid represents a particular type of expression, but it is 
 context-dependent.   Its a typical practicality beats purity type of 
 decision (like the rest of SQLA...)
 
 Well we're just trying out what SQLA is capable of at the moment and trying 
 to build up a proper api. We run into a similar issue then:
 
 We have an entity Party which has n Language through PartyLanguage. On 
 PartyLanguage there is a field called order. The one with the lowest 
 order is the parties primary language. Now it would be very pretty to be 
 able to do those things:
 
 1. someparty.primary_language = Language('en')
 2. assert someparty.primary_language == Language('en')
 3. someparty.languages.append(Language('de'))
 4. session.query(Party).filter(Party.primary_language=Language('en')).all()
 
 don't you think so? But we enquire a whole lot of problems. We managed to do 
 most things except for 4. We implemented @primary_language.expression like 
 this:
 
 @primary_language.expression
 def _primary_language_expression(cls):
 return Session().query(Language.iso)\
 .join(PartyLanguage)\
 .order_by(PartyLanguage.order)\
 .group_by(PartyLanguage.party_id, Language.iso, 
 PartyLanguage.order)\
 .having(PartyLanguage.party_id==cls.id)\
 .limit(1)\
 .as_scalar()

It doesn't always perform as well but the more relational way to do these is 
to use a subquery that selects the min() order:

select party_id, min(order) from party_language group by party_id

 -

select * from party_language as pl join language as lon 
pl.language_id=l.id
join (
select party_id, min(order) as order_id from party_language 
group by party_id
) as min_order
on min_order.order_id=pl.order_id and pl.party_id=min_order.party_id



 
 This works so far but there is still the need to use it in a query like this: 
 
 language = Language('en')
 session.query(Party).filter(Party.primary_language=language.iso).all()

language.iso is a string ?  object ?  You'd just need to have something 
there which is comparable to Language.iso.

A key approach here is to work out the queries first as SQL if needed, then as 
ORM queries, and only at the end figure out what you'd want a @hybrid to do.   
@hybrid is just a syntactical trick.

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

[sqlalchemy] Is outerjoin() not generative?

2011-02-15 Thread Michael Hipp

This works:
Seller = aliased(Dealer)
Buyer = aliased(Dealer)
q = self.session.query(Car, Seller.name, Buyer.name)
q = q.outerjoin((Car.seller, Seller), (Car.buyer, Buyer))

This doesn't:
Seller = aliased(Dealer)
Buyer = aliased(Dealer)
q = self.session.query(Car, Seller.name, Buyer.name)
q = q.outerjoin(Car.seller, Seller)
q = q.outerjoin(Car.buyer, Buyer)

sqlalchemy.exc.ArgumentError: Can't determine join between 'Join object on 
cars(71352432) and dealers(71704656)' and '%(78454064 dealers)s'; tables have 
more than one foreign key constraint relationship between them. Please specify 
the 'onclause' of this join explicitly.


Is this by design?

Thanks,
Michael

--
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] Is outerjoin() not generative?

2011-02-15 Thread Michael Bayer

On Feb 15, 2011, at 5:21 PM, Michael Hipp wrote:

 This works:
Seller = aliased(Dealer)
Buyer = aliased(Dealer)
q = self.session.query(Car, Seller.name, Buyer.name)
q = q.outerjoin((Car.seller, Seller), (Car.buyer, Buyer))
 
 This doesn't:
Seller = aliased(Dealer)
Buyer = aliased(Dealer)
q = self.session.query(Car, Seller.name, Buyer.name)
q = q.outerjoin(Car.seller, Seller)
q = q.outerjoin(Car.buyer, Buyer)
 
 sqlalchemy.exc.ArgumentError: Can't determine join between 'Join object on 
 cars(71352432) and dealers(71704656)' and '%(78454064 dealers)s'; tables have 
 more than one foreign key constraint relationship between them. Please 
 specify the 'onclause' of this join explicitly.
 
 Is this by design?


the target goes first for target, onclause, syntax, note this is an 0.7 
syntax:

q = q.outerjoin(Seller, Car.seller)
q = q.outerjoin(Buyer, Car.buyer)

in 0.6 you need the tuples for target, onclause:

q = q.outerjoin((Seller, Car.seller))
q = q.outerjoin((Buyer, Car.buyer))

Consult http://www.sqlalchemy.org/docs/orm/tutorial.html#querying-with-joins  
and 
http://www.sqlalchemy.org/docs/orm/query.html#sqlalchemy.orm.query.Query.join 
for reference on this.

in this case you are using a property as the on which includes the left and 
right points, so you don't really need the target, the single-arg form works:

q = q.outerjoin(Car.seller)
q = q.outerjoin(Car.buyer)


the onclause, target form is a legacy syntax which is why it still attempts 
to work.


 
 Thanks,
 Michael
 
 -- 
 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] Pypi release policy

2011-02-15 Thread Eric Lemoine
On Tuesday, February 15, 2011, Tarek Ziadé ziade.ta...@gmail.com wrote:
 On Tue, Feb 15, 2011 at 3:27 PM, Eric Lemoine
 eric.lemo...@camptocamp.com wrote
 ..

 But aren't apps supposed to use =0.6.99 to avoid backward compats
 issues? Apps that don't will also break when 0.7 final is on pypi.

 There are different things here:

 1/ PyPI allows projects to publish any release, and easy_install will
 pick the latest one, whether it's a final (==stable) or not. You can
 publish your trunk if you want.

 2/ An application that defines a dependency can define it in different 
 flavors:

 a - Give me the latest release that was made available at PyPI
 b - Give me the latest release from the 0.6.x series,   it can use a
 0.7 or 0.6.99
 c - Give me version XX   --- best practice once in production


 For applications that are using 2.a, the interpretation of most people
 is that the latest release at PyPI they are depending on is not a
 development release. If they want a development release, they do it
 explicitly in their environment to leave on the edge.

 3/ a user types easy_install SQLAlchemy and wants the latest stable

 So, yeah, when 0.7.1 final will be out, some apps will break -- but
 they've been warned and they can choose to change their code or pin
 their dependency to the 0.6.x series. But right now, it's a
 development release that has been published for feedback as opposed to
 a final release.

 The less disruptive process (until distutils2 is available) in that
 case is to let people opt in to be beta testers, and let SQLAlchemy
 means latest stable, whether it's called by easy_install
 SQLAlchemy or in the install_requires option in setuptools.


Thanks for the detailed response Tarek. It means that beta testers
won't be able to download SQLAlchemy betas from PyPI, and will have to
install betas from source?

Cheers,

-- 
Eric Lemoine

Camptocamp France SAS
Savoie Technolac, BP 352
73377 Le Bourget du Lac, Cedex

Tel : 00 33 4 79 44 44 96
Mail : eric.lemo...@camptocamp.com
http://www.camptocamp.com

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