[sqlalchemy] Re: Mapping and querying multiple levels of foreign key'd tables

2008-03-05 Thread Christoph Haas

On Wed, Mar 05, 2008 at 08:31:12AM +0100, Christoph Haas wrote:
 Basically I have three tables like 'companies', 'departments' and
 'employees'. I have already set up foreign keys and gave all of them
 one-to-many relationships. So a company has several departments. And
 each department has several employees. So for an ORM-mapped company
 object mycompany I can get the departments by the property
 mycompany.departments. Works well.
 
 Now I'd like to create a query for all employees of a certain company. 
 And I'm not sure how to properly define a mapper relation propery that
 would give me that. Like mycompany.employees. Do I have to use JOINs
 myself in the mapper?
 
 In my application I'd then like to query like this:
 Session.query(Employee).filter_by(employee.company=my_company)

Meanwhile I re-read
http://www.sqlalchemy.org/docs/04/ormtutorial.html#datamapping_joins
explaining that a relation path A-bars-B-bats-C-widgets-D is
queried as:

session.query(Foo).join(['bars', 'bats', 'widgets']).filter(...)

So in my example I already managed to get this working:

session.query(Employee)join(['department','company']). \
filter(model.Company.id==mycompany.id)

Is this the common way to deal with CompanyDepartment-Employee paths?
If it is - can I perhaps even omit the .id part somehow? I tried:

session.query(Employee)join(['department','company']). \
filter(model.Company==mycompany)

But SQLAlchemy didn't like that:

ArgumentError: filter() argument must be of type
sqlalchemy.sql.ClauseElement or string

Thanks for any comments.

 Christoph
-- 
[EMAIL PROTECTED]  www.workaround.org   JID: [EMAIL PROTECTED]
gpg key: 79CC6586 fingerprint: 9B26F48E6F2B0A3F7E33E6B7095E77C579CC6586

--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Integrating the ORM with Trellis

2008-03-05 Thread Michael Bayer


On Mar 4, 2008, at 7:27 PM, Phillip J. Eby wrote:


 Okay, so I did a matching uninstrument_attribute and
 pre_uninstrument_attribute, which look like really dumb names at this
 point.  I propose the following name changes (in addition to the ones
 in my previous patch):

 pre_instrument_attribute - install_descriptor
 pre_uninstrument_attribute - uninstall_descriptor

 That okay?  instrument_attribute will then call install_descriptor to
 do the actual installing.  And of course the hooks on the adapted
 thingy from the class would work the same way.

 If that's okay with you, then after I'm done I'll post a patch for
 review before checkin.  After that, I'll start work on the
 Trellis-side support for this, and then eventually dig into   
 collections stuff.

hey phillip -

It all sounds great to me !  I think its been established in the past  
several months that my names are generally pretty bad so I usually  
defer to others at this point.

- mike



--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Python 2.6 hash behavior change

2008-03-05 Thread Michael Bayer


On Mar 5, 2008, at 3:35 AM, Denis S. Otkidach wrote:

 All hash table implementations (including one in Python) work the same
 way: first it looks up a list of key-value pairs by hash, and then
 iterate through the list to find a needed key by comparing it with =
 operator. Thus __eq__ method _is_ used to lookup values in
 dictionaries. So, this won't work in some cases:
 1) when __eq__ may return False when comparing to identical (but not
 the same, since Python always checks with is first),
 2) when __eq__ may return True for objects we want to be assumed
 different - in some rare cases when they produce the same hash.

 Although both are not our cases (we always return True, and using id()
 for hash guarantees they will never clash), I believe your suggestion
 to use IdentitySet and IdentityDict is a right direction.

I want to establish a Expression-friendly token in the source code  
for sets and dicts such that we can change underlying implementations  
as needed.  We were doing some source code browsing yesterday and it  
seems to use __cmp__() for the equality check - so we might not need  
to move to IdentitySet/Dict just yet.

My knowledge of hashtables says that two objects with different hash  
values can still be subject to the equality comparison if they are  
placed in the same bucket, so we do need to worry about equality  
comparison in any case.

We have filed http://bugs.python.org/issue2235 to deal with __hash__  
not being checked along an inheritance hierarchy so at least as far as  
2.6, we will be able to make a base class that provides a default  
__hash__() method, but it seems like Guido in py3k wants __hash__()  
and __eq__() to always be redefined at the same level.It seems  
overly rigid to me but I'm not the person to take up an argument about  
that (any takers ? :)  ).

It seems like the long term approach here is to get really nice  
IdentitySet and IdentityDicts going, and this may even be a place I  
want to start looking into optional, native extensions for performance  
purposes.

--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Intersect of ORM queries

2008-03-05 Thread svilen

pardon my sql-ignorancy, but cant u express this in just one 
expression? it should be possible, it is a graph/set arithmetics 
after all... 
mmh, (could be very wrong!) something like 
 - get all rows that has some b_id from the looked list
 - group(?) somehow by a_id, and then finger the a_id which collection 
of b's matches the looked list.
on 2nd thought, maybe no, this is a procedural way, not a 
set-arithmetics way...

On Wednesday 05 March 2008 17:23:52 Eric Ongerth wrote:
 I know how to issue an Intersect of multiple Selects, but I am
 wondering if there is a simple way to seek the intersection of
 multiple ORM queries.  I already know how to get the results I want
 in pure SQL or in SA-assisted non-ORM statements.  I just wonder if
 I could use sqlalchemy even more powerfully in the case of a
 particular M:M relationship in my model.

 Here's the situation, very simple.  Table a is mapped to class A,
 and table b mapped to class B.  I have a many:many relationship
 between class A and class B, via a secondary table whose only
 columns are a_id and b_id.  What I'm looking for is, I have a list
 of Bs and I want to find the (single) A that has exactly those same
 Bs in its Bs collection.  (I know the results will either be a
 single A or None, because of certain uniqueness constraints that
 don't matter to this question).

 So to do this with selects, this should work fine: (pardon the
 pseudo- SQL)
 intersect(
 select a_id from secondary_table where b_id ==
 b_being_sought[0].id,
 select a_id from secondary_table where b_id ==
 b_being_sought[1].id,
 ...
 select a_id from secondary_able where b_id ==
 b_being_sought[n].id
 )

  -- Easily generated with a Python loop over the list of B's that
 I'm searching for.

 So each of those selects returns a number of rows from the
 secondary table, all linked to ONE of the B's in the list; and the
 intersect returns the single (or none) row in the secondary table
 which refers to the A which has *all* of those B's in its B
 collection.

 Fine.  But it would be so syntactically smooth if I could just do
 something like:
 intersect(
 query(A).filter(b=b_being_sought[0]),
 query(A).filter(b=b_being_sought[1]),
 ...
 query(A).filter(b=b_being_sought[n])
 )

 Is this possible in some way?  I haven't found a way to make this
 work ORM-style, because intersect() only wants select statements. 
 Am I correct in thinking that I could build each ORM query, steal
 its where_clause and use those where_clauses as my set of selects
 for the intersect()?  But that is enough extra steps, and enough
 exposition of internals, to clearly make it a confusing and
 backwards way of getting the results I want.  Definitely not a path
 to more readable code -- if that were the only way, then I would
 just do it the non-ORM way above.

 All comments appreciated.
 


--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Intersect of ORM queries

2008-03-05 Thread Michael Bayer


On Mar 5, 2008, at 10:50 AM, Eric Ongerth wrote:

 Anyway -- so what would really clean it all up would be:

 session.query(A).filter(A.bs.contains(list_of_bs_being_sought)).all().

 THAT would do exactly what I'm trying to accomplish.  But it would
 require contains() to accept a list and know what to do with it.  My
 proposal would be that the expected behavior is for contains() to
 construct an intersect of selects where each select is like the one it
 creates in its simpler case where the argument to contains() is a
 scalar instead of a list.  Does that make sense?

Well i think we'd call the operator intersect().  However I think this  
will do what you want right now if you were to say:

session.query(A).filter(A.bs == list_of_bs).all()

since it will generate individual EXISTS predicates for each element  
in the list.


--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] InstrumentedList in SA 0.4.3

2008-03-05 Thread Acm

With SA version 0.3.11 I used to import InstrumentedList as follows:
  from sqlalchemy.orm.attributes import InstrumentedList

Now I upgraded to SA 0.4.3 and cannot import InstrumentedList from the
same file.

I looked into the SQLAlchemy file attribute.py and noticed that this
file uses the import as in version 0.3.11

Should I use class InstrumentedAttribute instead of InstrumentedList?
Or else, how can I import InstrumentedList to my files?

Thanks
--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Mapping and querying multiple levels of foreign key'd tables

2008-03-05 Thread Christoph Haas

Moin, Michael...

thanks for your quick reply.

On Wed, Mar 05, 2008 at 11:16:33AM -0500, Michael Bayer wrote:
 On Mar 5, 2008, at 4:14 AM, Christoph Haas wrote:
  Meanwhile I re-read
  http://www.sqlalchemy.org/docs/04/ormtutorial.html#datamapping_joins
  explaining that a relation path A-bars-B-bats-C-widgets-D is
  queried as:
 
 session.query(Foo).join(['bars', 'bats', 'widgets']).filter(...)
 
  So in my example I already managed to get this working:
 
 session.query(Employee)join(['department','company']). \
 filter(model.Company.id==mycompany.id)
 
  Is this the common way to deal with CompanyDepartment-Employee  
  paths?
  If it is - can I perhaps even omit the .id part somehow? I tried:
 
 session.query(Employee)join(['department','company']). \
 filter(model.Company==mycompany)
 
  But SQLAlchemy didn't like that:
 
 ArgumentError: filter() argument must be of type
 sqlalchemy.sql.ClauseElement or string
 
 you want to compare Employee.department.company to the element you  
 have, so it would be:
 
   session.query(Employee).join('department').filter(Department.company  
 == mycompany)

Oh, right. That saves the second JOIN as the department.company_id is
already a field on the departments. Yet another case of thinking too
abstract instead of remembering how the actual database tables look. :)

 or even cooler, you could do

 session.query(Employee).filter(Employee.department.has(
   Department.company==mycompany))

Somehow .has and .any have always been somewhat magical to me. I think
I'll rather use the less cool way because it's more likely I understand
my code then in a few years. Works well, thanks. So I was basically on
the right track with the JOIN.

But now I'm curious. Why do I get the ArgumentError if I try

.filter(Company==my_company)

while

.filter(Company.id==my_company.id)

works? I was comparing ORM objects directly instead of fields/properties
of a mapped object. But shouldn't that work, too?

Cheers
 Christoph
-- 
[EMAIL PROTECTED]  www.workaround.org   JID: [EMAIL PROTECTED]
gpg key: 79CC6586 fingerprint: 9B26F48E6F2B0A3F7E33E6B7095E77C579CC6586

--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Mapping and querying multiple levels of foreign key'd tables

2008-03-05 Thread Michael Bayer


On Mar 5, 2008, at 1:00 PM, Christoph Haas wrote:


 But now I'm curious. Why do I get the ArgumentError if I try

.filter(Company==my_company)

 while

.filter(Company.id==my_company.id)

 works? I was comparing ORM objects directly instead of fields/ 
 properties
 of a mapped object. But shouldn't that work, too?

The relation()-based descriptors are the ones which are aware of  
comparisons to instances, i.e. Department.company==somecompany.  Try  
saying print Department.company==mycompany to see how that works. 
  

--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] proposed FAQ entry

2008-03-05 Thread David Gardner

Ran into something this morning, fix and problem are simple.
Q) How do I map a column that is a Python reserved word or already used 
by SA?
A)
table_a = Table ('tbl_a', metadata, autoload=True)
mapper(AObj, table_a, properties={'type_col' : table_a.c.type, 
'pass_col':table_a.c['pass']})

This may be covered under 3.1 I am using autoload=True and insert your 
problem here, but I think type is a common enough column name.


--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Intersect of ORM queries

2008-03-05 Thread Eric Ongerth

Cool.  I wasn't sure if it was ready for filter(A.bs == list_of_bs).
When I tried to do that before, I must have let some silly syntax
error keep me from realizing that it was a workable construction.

Thanks!

On Mar 5, 8:20 am, Michael Bayer [EMAIL PROTECTED] wrote:
 On Mar 5, 2008, at 10:50 AM, Eric Ongerth wrote:

  Anyway -- so what would really clean it all up would be:

  session.query(A).filter(A.bs.contains(list_of_bs_being_sought)).all().

  THAT would do exactly what I'm trying to accomplish.  But it would
  require contains() to accept a list and know what to do with it.  My
  proposal would be that the expected behavior is for contains() to
  construct an intersect of selects where each select is like the one it
  creates in its simpler case where the argument to contains() is a
  scalar instead of a list.  Does that make sense?

 Well i think we'd call the operator intersect().  However I think this
 will do what you want right now if you were to say:

 session.query(A).filter(A.bs == list_of_bs).all()

 since it will generate individual EXISTS predicates for each element
 in the list.
--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---