Re: [sqlalchemy] Relate to Object by Two Refs

2013-05-16 Thread Wichert Akkerman

On May 16, 2013, at 03:09 , Ji Zhang zhangj...@gmail.com wrote:

 Hi,
 
 Say I have a Request model and User model:
 
 class Request(Base):
   id = Column(Integer, primary_key=True)
   user_id = Column(Integer)
   admin_id = Column(Integer)
 
 class User(Base):
   id = Column(Integer, primary_key=True)
   username = Column(String)
 
 The Request is created by a user (User) and get verified by an admin (also a 
 User). How to get both request.user and request.admin?

You will need to specify the foreign keys used for the relation ship:

class Request(Base):
user_id = Column(Integer, ForeignKey('user.id'))
user = relationship(User, foreign_keys=[user_id])
admin_id = Column(Integer, ForeignKey('user.id'))
admin = relationship(User, foreign_keys=[admin_id])

You can find more details in the SQLAlchemy documentation: 
http://docs.sqlalchemy.org/en/rel_0_8/orm/relationships.html#handling-multiple-join-paths

Wichert.

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




Re: [sqlalchemy] Metadata default schema

2013-05-16 Thread rdunklau
My bad, I didn't notice those notes in the documentation, thank you for 
pointing that out.

I understand the reason for the table test1 showing twice, but why doesn't 
it when I reflect the public schema (explicitly, not via the None default 
schema) after the test2 table ?
If I understand correctly, the test2 table reflection should point to the 
(unqualified) test1 table, thus resulting in the test1 table being created 
in the default schema.
Shouldn't reflecting the public schema after that create another 
public.test1 table for the sake of consistency ?



Le mercredi 15 mai 2013 17:24:59 UTC+2, Michael Bayer a écrit :


 On May 15, 2013, at 4:37 AM, Ronan Dunklau rdun...@gmail.comjavascript: 
 wrote: 

  Hello. 
  
  I'm sorry if this has already been reported, but I couldn't find it. 
  
  The metadata schema defaults to None, which can lead to suprising and   
  inconsistent results when reflecting tables from various schemas. I 
 don't know 
  what the behaviour should be exactly, but this doesn't seem right. 
  
  This has been tested on sqlalchemy 0.8.1, with postgresql. I don't know 
 if 
  this is specific to the postgresql backend. Please find the sql and 
 python code 
  corresponding to the following scenario as attachments. 
  
  Let's say I have a table in a schema test_schema, which references a 
 table 
  test1 in the default schema, public. 
  
  If I reflect the public schema, then the test_schema schema, the test1 
 table 
  appear twice (once in the public schema, once in the None schema). 
  
  If I reflect the test_schema schema first, then the public schema, the 
 test1 
  table appear only once, in the None schema. 
  
  If I reflect the default schema first (None), which should be the same 
 as the 
  public schema, the test1 table appear only once, as it should be. 
  
  A simple workaroud for this is to initialize the metadata schema 
 attribute 
  with the default schema name as found in the 
 Inspector.default_schema_name 
  attribute. 

 so the notes for this situation are here: 
 http://docs.sqlalchemy.org/en/rel_0_8/dialects/postgresql.html#remote-cross-schema-table-introspection
  

 When we reflect the test_schema.test2 table and receive its collection of 
 foreign keys, Postgresql  tells us the table refers to another table called 
 test1, but does *not* tell us which schema this table is present within. 
   This is because the public schema is in the search path, and it is 
 omitted.If we were able to see public, we would know that we already 
 have a table present called public.test1 which fits the bill, but we 
 don't, and this would also be a behavioral inconsistency.   The behavior of 
 the table inspection in any case is that the default schema of the 
 connection corresponds to a schema of None for the reflected table. 

 As the notes there say, the expected model is that the search_path is set 
 to public only, and that Table objects which refer to public would use 
 None as the schema.It's true that other models here could work too, 
 having public be explicit in all cases, but using both models at the same 
 time doesn't seem to be feasible, at least not without some workarounds as 
 you've mentioned. 




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




Re: [sqlalchemy] Metadata default schema

2013-05-16 Thread Michael Bayer
a little bit of a slip in metadata.reflect(), there's a patch which potentially 
fixes this in http://www.sqlalchemy.org/trac/ticket/2728.


On May 16, 2013, at 3:35 AM, rdunklau rdunk...@gmail.com wrote:

 My bad, I didn't notice those notes in the documentation, thank you for 
 pointing that out.
 
 I understand the reason for the table test1 showing twice, but why doesn't it 
 when I reflect the public schema (explicitly, not via the None default 
 schema) after the test2 table ?
 If I understand correctly, the test2 table reflection should point to the 
 (unqualified) test1 table, thus resulting in the test1 table being created in 
 the default schema.
 Shouldn't reflecting the public schema after that create another public.test1 
 table for the sake of consistency ?
 
 
 
 Le mercredi 15 mai 2013 17:24:59 UTC+2, Michael Bayer a écrit :
 
 On May 15, 2013, at 4:37 AM, Ronan Dunklau rdun...@gmail.com wrote: 
 
  Hello. 
  
  I'm sorry if this has already been reported, but I couldn't find it. 
  
  The metadata schema defaults to None, which can lead to suprising and   
  inconsistent results when reflecting tables from various schemas. I don't 
  know 
  what the behaviour should be exactly, but this doesn't seem right. 
  
  This has been tested on sqlalchemy 0.8.1, with postgresql. I don't know if 
  this is specific to the postgresql backend. Please find the sql and python 
  code 
  corresponding to the following scenario as attachments. 
  
  Let's say I have a table in a schema test_schema, which references a table 
  test1 in the default schema, public. 
  
  If I reflect the public schema, then the test_schema schema, the test1 
  table 
  appear twice (once in the public schema, once in the None schema). 
  
  If I reflect the test_schema schema first, then the public schema, the 
  test1 
  table appear only once, in the None schema. 
  
  If I reflect the default schema first (None), which should be the same as 
  the 
  public schema, the test1 table appear only once, as it should be. 
  
  A simple workaroud for this is to initialize the metadata schema 
  attribute 
  with the default schema name as found in the Inspector.default_schema_name 
  attribute. 
 
 so the notes for this situation are here: 
 http://docs.sqlalchemy.org/en/rel_0_8/dialects/postgresql.html#remote-cross-schema-table-introspection
  
 
 When we reflect the test_schema.test2 table and receive its collection of 
 foreign keys, Postgresql  tells us the table refers to another table called 
 test1, but does *not* tell us which schema this table is present within.   
 This is because the public schema is in the search path, and it is omitted. 
If we were able to see public, we would know that we already have a 
 table present called public.test1 which fits the bill, but we don't, and 
 this would also be a behavioral inconsistency.   The behavior of the table 
 inspection in any case is that the default schema of the connection 
 corresponds to a schema of None for the reflected table. 
 
 As the notes there say, the expected model is that the search_path is set to 
 public only, and that Table objects which refer to public would use 
 None as the schema.It's true that other models here could work too, 
 having public be explicit in all cases, but using both models at the same 
 time doesn't seem to be feasible, at least not without some workarounds as 
 you've mentioned. 
 
 
 
 -- 
 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.
  
  

-- 
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] how are foreign relations stored ?

2013-05-16 Thread Jonathan Vanasco
I've been using a utility method 'columns_as_dict' to help store my data in 
a cache.  It works well.

A problem I've encountered... i need to access the related data that i've 
eagerloaded.

My current function looks like this

def columns_as_dict(self):
as_dict = dict(
   (col.name, getattr(self, col.name)) 
   for col in 
sqlalchemy_orm.class_mapper(self.__class__).mapped_table.c
)
return *as_dict*
*
*
any idea how i can access the foreign relations ?  i'm specifically interested 
in ones that are already eagerloaded, but am also interested in accessing all 
of the relations in general.

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




Re: [sqlalchemy] how are foreign relations stored ?

2013-05-16 Thread Michael Bayer
if you're on 0.8 this is all available via the various getters on mapper: 
http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html#sqlalchemy.orm.mapper.Mapper.attrs


On May 16, 2013, at 1:37 PM, Jonathan Vanasco jonat...@findmeon.com wrote:

 I've been using a utility method 'columns_as_dict' to help store my data in a 
 cache.  It works well.
 
 A problem I've encountered... i need to access the related data that i've 
 eagerloaded.
 
 My current function looks like this
 
 def columns_as_dict(self):
 as_dict = dict(
(col.name, getattr(self, col.name)) 
for col in 
 sqlalchemy_orm.class_mapper(self.__class__).mapped_table.c
 )
 return as_dict
 
 any idea how i can access the foreign relations ?  i'm specifically 
 interested in ones that are already eagerloaded, but am also interested in 
 accessing all of the relations in general.
 
 -- 
 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.
  
  

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




Re: [sqlalchemy] how are foreign relations stored ?

2013-05-16 Thread Jonathan Vanasco
I am and that's awesome.  Thank you!

On Thursday, May 16, 2013 2:47:47 PM UTC-4, Michael Bayer wrote:

 if you're on 0.8 this is all available via the various getters on mapper: 
 http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html#sqlalchemy.orm.mapper.Mapper.attrs


 On May 16, 2013, at 1:37 PM, Jonathan Vanasco 
 jona...@findmeon.comjavascript: 
 wrote:

 I've been using a utility method 'columns_as_dict' to help store my data 
 in a cache.  It works well.

 A problem I've encountered... i need to access the related data that i've 
 eagerloaded.

 My current function looks like this

 def columns_as_dict(self):
 as_dict = dict(
(col.name, getattr(self, col.name)) 
for col in 
 sqlalchemy_orm.class_mapper(self.__class__).mapped_table.c
 )
 return *as_dict*
 *
 *
 any idea how i can access the foreign relations ?  i'm specifically 
 interested in ones that are already eagerloaded, but am also interested in 
 accessing all of the relations in general.


 -- 
 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+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.comjavascript:
 .
 Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
 For more options, visit https://groups.google.com/groups/opt_out.
  
  




-- 
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] Relationship configuration that isn't functioning as I expect

2013-05-16 Thread Bobby Impollonia
I am trying to create a relationship to work with a legacy schema and am 
having trouble configuring it to behave as I want. As a disclaimer, I 
understand why the schema here is not the schema one would use if starting 
from scratch.

Anyway, I have simplied the situation down to the following example:
I have users and have two different types of objects that users can be 
related to. For this example, those are street addresses and email 
addresses. Rather than having a secondary table for each relationship, 
there is a single secondary table. It has a foreign key column that will 
either function as a foreign key to the street addresses table or the email 
addresses table. There is a discriminator column that indicates which of 
those tables is being referenced. The secondary table has its own primary 
key and has an associated mapped class. The problem I am trying to solve is 
setting up a relationship between the secondary table and the address 
tables.

This is what I have ended up with:

class Affiliation(Base):
__tablename__ = 'affiliations'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
address_type = Column(String, nullable=False)
address_id = Column(Integer, nullable=False)

user = relationship(User, backref='affiliations')
email_address = relationship(
'EmailAddress',
primaryjoin=and_(address_type == 'email',
 address_id  == EmailAddress.id),
foreign_keys=[address_id],
viewonly=True)
street_address = relationship(
'StreetAddress',
primaryjoin=and_(address_type == 'street',
 address_id  == StreetAddress.id),
foreign_keys=[address_id],
viewonly=True)


The users, email_addresses and street_addresses tables/ classes are trivial 
so I am omitting them from this post, but I have a full working example 
here:
https://gist.github.com/bobbyi/5593984

For a given affiliation, I want affiliation.email_address to be 
the appropriate email address if this affiliation's type is 'email'. 
Otherwise, it should be None.

Given the following:
affiliation = session.query(Affiliation).get(1)
print affiliation.email_address

The SQL generated by the second line is:
SELECT email_addresses.id AS email_addresses_id, email_addresses.address AS 
email_addresses_address
FROM email_addresses, affiliations
WHERE affiliations.address_type = 'email' AND 1 = email_addresses.id

Note that this is a cartesian join.

I hoped to end up with something like:
SELECT email_addresses.id AS email_addresses_id, email_addresses.address AS 
email_addresses_address
FROM email_addresses, affiliations
WHERE affiliations.address_type = 'email' AND affiliations.address_id = 
email_addresses.id AND affiliations.id = 1

Two questions:
1) Is the behavior I am seeing here expected given my relationship 
configuration?
2) How can I configure my relationship to exhibit the desired behavior in 
the situation shown above?

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




Re: [sqlalchemy] EAV Optimizations

2013-05-16 Thread Lycovian
I believe it was for some work you did for Akiban.  If I remember correctly 
(ha!) I believe you detailed with some slides an updated join strategy that 
they are using (or that you hacked) into a custom version of SA used by 
them.  I noted the demo as I am planning on using EAV for a personal 
project and was wondering if that updated EAV join strategy code would make 
it into the released version of SA.  From your slides I think you showed 
that the number of joins on the EAV tables with the updated strategy was 
significantly reduced.  Sorry I can't remember more.

As a side note EAV is not a panacea but I have used it to great effect in 
the past judiciously.  In the application in question we had millions of 
digital assets in effectively a proprietary photo library used by Sony. 
 All of the data for the application except the binary asset was stored in 
the DB (Oracle in this case).  The requirement for the project was that the 
users could also annotate their assets with security descriptors, groups, 
and any other typed metadata they wished, including links to other assets 
to create packages of assets.  The metadata key/value count was going to 
be in the billions of facts.  As such we made the decision to make the 
entire of the metadata schema EAV including internal metadata (security, 
stock keys such as create date, name, path, etc).  By putting all of the 
metadata in EAV we were able to also employ such niceties as indexes for 
speed and table level constraints (as well as triggers for certain keys and 
other business logic in PL/SQL).  The EAV method though did add some 
complexity to the application queries which we abstracted away by using 
some Ruby ORM libs that could work natively with EAV schemas hiding most of 
the complexity of the schema implementation from the application engineers. 
 Over all the project was a big success and I believe is still in use with 
many billions of records, all without requiring the use of a secondary 
key/value document store with differing query semantics and iffy indexing 
and constraint enforcement.  I wouldn't use EAVs for everything, not by a 
long shot, but properly implemented and indexed they work great in my 
practical experience.

Mike 

On Monday, May 13, 2013 5:26:01 PM UTC-7, Michael Bayer wrote:

 what video is that ?I don't use EAV's too often.   If you can point me 
 to something I can identify what it was.

 On May 13, 2013, at 8:22 PM, Lycovian mfwi...@gmail.com javascript: 
 wrote:

 A few months ago I watched a video conference where Mike demo'd some 
 optimizations for SQLAlchemy when using EAV schemas.  Does anyone know if 
 these optimizations will make it into the product that we have access to? 
  I'm about to start a large EAV based project with SA and I was curious.

 Mike

 -- 
 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+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.comjavascript:
 .
 Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
 For more options, visit https://groups.google.com/groups/opt_out.
  
  




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




Re: [sqlalchemy] EAV Optimizations

2013-05-16 Thread Michael Bayer
oh, yeah I don't have that code, that was Ori talking about a particular client 
integration they had, where they went bananas with EAV.   The point there was 
to show how Akiban does a much better job querying structures like that, but I 
had no involvement in that gig.

The EAV stuff I have, you can look in examples/vertical/ for a few old ones, 
then there's the http://www.sqlalchemy.org/trac/wiki/UsageRecipes/VersionedMap 
recipe which is more or less like the one I use in my current work, that's 
about it.

As for use case, I'm all in favor of judicious use of almost anything.   I 
don't respond well to the never do XYZ! thing, I feel like there should be a, 
* unless you have more than 10 years of experience clause (see 
http://norvig.com/21-days.html for background).  I use, to a greater or lesser 
extent, all the baddies: global variables, mixins, multiple inheritance, EAVs, 
explicit locking, ORM queries in my controllers, all of it, if it's been called 
bad I've probably got it in production in a very judicious and pragmatic way, 
without problems.




On May 16, 2013, at 3:48 PM, Lycovian mfwil...@gmail.com wrote:

 I believe it was for some work you did for Akiban.  If I remember correctly 
 (ha!) I believe you detailed with some slides an updated join strategy that 
 they are using (or that you hacked) into a custom version of SA used by them. 
  I noted the demo as I am planning on using EAV for a personal project and 
 was wondering if that updated EAV join strategy code would make it into the 
 released version of SA.  From your slides I think you showed that the number 
 of joins on the EAV tables with the updated strategy was significantly 
 reduced.  Sorry I can't remember more.
 
 As a side note EAV is not a panacea but I have used it to great effect in the 
 past judiciously.  In the application in question we had millions of digital 
 assets in effectively a proprietary photo library used by Sony.  All of the 
 data for the application except the binary asset was stored in the DB (Oracle 
 in this case).  The requirement for the project was that the users could also 
 annotate their assets with security descriptors, groups, and any other typed 
 metadata they wished, including links to other assets to create packages of 
 assets.  The metadata key/value count was going to be in the billions of 
 facts.  As such we made the decision to make the entire of the metadata 
 schema EAV including internal metadata (security, stock keys such as create 
 date, name, path, etc).  By putting all of the metadata in EAV we were able 
 to also employ such niceties as indexes for speed and table level constraints 
 (as well as triggers for certain keys and other business logic in PL/SQL).  
 The EAV method though did add some complexity to the application queries 
 which we abstracted away by using some Ruby ORM libs that could work natively 
 with EAV schemas hiding most of the complexity of the schema implementation 
 from the application engineers.  Over all the project was a big success and I 
 believe is still in use with many billions of records, all without requiring 
 the use of a secondary key/value document store with differing query 
 semantics and iffy indexing and constraint enforcement.  I wouldn't use EAVs 
 for everything, not by a long shot, but properly implemented and indexed they 
 work great in my practical experience.
 
 Mike 
 
 On Monday, May 13, 2013 5:26:01 PM UTC-7, Michael Bayer wrote:
 what video is that ?I don't use EAV's too often.   If you can point me to 
 something I can identify what it was.
 
 On May 13, 2013, at 8:22 PM, Lycovian mfwi...@gmail.com wrote:
 
 A few months ago I watched a video conference where Mike demo'd some 
 optimizations for SQLAlchemy when using EAV schemas.  Does anyone know if 
 these optimizations will make it into the product that we have access to?  
 I'm about to start a large EAV based project with SA and I was curious.
 
 Mike
 
 -- 
 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+...@googlegroups.com.
 To post to this group, send email to sqlal...@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.
  
  
 
 
 -- 
 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.
  
  

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving 

Re: [sqlalchemy] EAV Optimizations

2013-05-16 Thread Julien Cigar

On 05/14/2013 16:58, Michael Bayer wrote:

When you are storing data with key/values, where the set of keys is part of the 
data.   Storing configurational data is the main use case.HSTORE not an 
option because it is postgresql-specific.


Yes it may be acceptable to store configurational data (although I would 
probably use HSTORE under PostgreSQL). But a large EAV based project 
sounds terribly bad to me.






On May 14, 2013, at 10:49 AM, Julien Cigar jci...@ulb.ac.be wrote:


On 05/14/2013 16:09, Michael Bayer wrote:

EAVs have a definite place and with judicious use they are extremely useful.

just curious: could you give an example where EAV is useful ?


On May 14, 2013, at 4:37 AM, Julien Cigar jci...@ulb.ac.be wrote:


On 05/14/2013 02:22, Lycovian wrote:

A few months ago I watched a video conference where Mike demo'd some 
optimizations for SQLAlchemy when using EAV schemas.  Does anyone know if these 
optimizations will make it into the product that we have access to?  I'm about 
to start a large EAV based project with SA and I was curious.


please don't ... EAV is evil and has tons of disadvantages. I don't know about 
your database, but in PostgreSQL you have HSTORE and JSON which could often be 
used to replace EAV


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



--
No trees were killed in the creation of this message.
However, many electrons were terribly inconvenienced.

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




--
No trees were killed in the creation of this message.
However, many electrons were terribly inconvenienced.

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




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




Re: [sqlalchemy] EAV Optimizations

2013-05-16 Thread Michael Bayer

On May 16, 2013, at 4:07 PM, Julien Cigar jci...@ulb.ac.be wrote:

 On 05/14/2013 16:58, Michael Bayer wrote:
 When you are storing data with key/values, where the set of keys is part of 
 the data.   Storing configurational data is the main use case.HSTORE not 
 an option because it is postgresql-specific.
 
 Yes it may be acceptable to store configurational data (although I would 
 probably use HSTORE under PostgreSQL). But a large EAV based project sounds 
 terribly bad to me.

I agree, I've seen lots of projects where they base it all on EAV, and it's a 
terrible idea.   But I was lucky to get my everything-is-an-EAV thing done 
with by about 1998.


 
 
 
 
 On May 14, 2013, at 10:49 AM, Julien Cigar jci...@ulb.ac.be wrote:
 
 On 05/14/2013 16:09, Michael Bayer wrote:
 EAVs have a definite place and with judicious use they are extremely 
 useful.
 just curious: could you give an example where EAV is useful ?
 
 On May 14, 2013, at 4:37 AM, Julien Cigar jci...@ulb.ac.be wrote:
 
 On 05/14/2013 02:22, Lycovian wrote:
 A few months ago I watched a video conference where Mike demo'd some 
 optimizations for SQLAlchemy when using EAV schemas.  Does anyone know 
 if these optimizations will make it into the product that we have access 
 to?  I'm about to start a large EAV based project with SA and I was 
 curious.
 
 please don't ... EAV is evil and has tons of disadvantages. I don't know 
 about your database, but in PostgreSQL you have HSTORE and JSON which 
 could often be used to replace EAV
 
 Mike
 -- 
 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.
 
 
 -- 
 No trees were killed in the creation of this message.
 However, many electrons were terribly inconvenienced.
 
 -- 
 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.
 
 
 
 -- 
 No trees were killed in the creation of this message.
 However, many electrons were terribly inconvenienced.
 
 -- 
 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.
 
 
 
 -- 
 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.
 
 

-- 
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] Re: SQLServer + Datetimes returning odd results?

2013-05-16 Thread Bobby Impollonia
I think this value is coming from the underlying database driver rather 
than SQLAlchemy. If you execute the stored proc directly using the driver 
(I guess this is pymssql), do you see the same behavior? 

On Thursday, May 16, 2013 12:37:56 PM UTC-7, John Anderson wrote:

 I have a SQLServer DB with a table that has a column as datetime and its 
 default value is `getutcdate()` (on the server).

 We are using stored procedures and are running DBSession.execute('sproc') 
 and to do a select on the table and the rows that are returned have weird 
 datetime values:

 datetime.datetime(2013, 16, 136, 29, 231, 4, 3888128)

 It seems be be completely missing its month.  In the db the value is:

 2013-05-16 19:29:29.487

 Any ideas what might cause this?

 It is currently using SQLAlchemy 0.7.6


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




Re: [sqlalchemy] EAV Optimizations

2013-05-16 Thread Simon King

On 16 May 2013, at 21:21, Michael Bayer mike...@zzzcomputing.com wrote:

 
 On May 16, 2013, at 4:07 PM, Julien Cigar jci...@ulb.ac.be wrote:
 
 On 05/14/2013 16:58, Michael Bayer wrote:
 When you are storing data with key/values, where the set of keys is part of 
 the data.   Storing configurational data is the main use case.HSTORE 
 not an option because it is postgresql-specific.
 
 Yes it may be acceptable to store configurational data (although I would 
 probably use HSTORE under PostgreSQL). But a large EAV based project 
 sounds terribly bad to me.
 
 I agree, I've seen lots of projects where they base it all on EAV, and it's a 
 terrible idea.   But I was lucky to get my everything-is-an-EAV thing done 
 with by about 1998.
 

I have a project at the moment where I'm storing manufacturing test results. 
Each test is basically a big set of key/value pairs. The set of keys changes 
over time (as new tests are written), and one of the requirements for the 
database is that users be able to efficiently query specific values (for 
example to view trends over time).

My first attempt (written in 2006, using SQLAlchemy 0.3, and still running!) 
had a table for each test type, with columns for each measurement. The schema 
was tightly coupled to the test results, and every time a test was altered or 
added, I would have to change the code and alter the database to match. This is 
painful enough that I don't do it very often, so there are an increasing number 
of measurements which aren't stored in the database.

I've recently revisited the system, and had a go at using an EAV approach. So 
far I think I am approaching 100,000,000 values. I thought this might be a bit 
much for a single table, so I've split them across a number of tables, based on 
a hash of the key name. I'm not sure yet if that was a good idea, but it means 
I've got 256 tables with between 0 and 4,000,000 rows in. The tables have 3 
columns, 1 for the actual value, one is a foreign key to say which test the 
value belongs to, and the other is a foreign key to the table describing the 
key. Currently there are about 32000 distinct keys.

I don't think this would be a good match for HSTORE - I assume that retrieving 
values from HSTORE won't be as efficient as retrieving them from their own rows.

The new system is definitely much more flexible than the old, and there is a 
lot less code to maintain. I'm not sure about the performance yet - some of the 
queries feel slower than I think they should, but I haven't looked into it 
properly yet.

Simon

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




Re: [sqlalchemy] textcolumn.contains() escaping, the lack of icontains(), and possible bug?

2013-05-16 Thread Bobby Impollonia
Sounds like a useful feature.

Regarding case sensitivity, perhaps it would better if each of these 
methods (even like() and contains()) took a keyword argument along the 
lines of col.endswith('foo', case_sensitive=False) rather than adding extra 
methods with weird names like iendswith.

On Monday, May 13, 2013 3:44:38 PM UTC-7, Michael Bayer wrote:


 On May 13, 2013, at 6:30 PM, Daniel Grace thisgen...@gmail.comjavascript: 
 wrote:

 So today I identified a small bug in my code and then, while trying to 
 resolve it, came to a few realizations:

 1. column.contains(str) does not escape characters in str such as % and _. 
  Presumably, column.startswith(str) and column.endswith(str) have the same 
 behavior.


 this will be called autoescape and is ticket 2694: 
 http://www.sqlalchemy.org/trac/ticket/2694 .if someone wants to work 
 on a patch for this it would be v. helpful.   It's a little late to turn on 
 the escaping for all users now as it would break existing workarounds.



 2. There is a distinct lack of column.icontains(str), though the current 
 implementation means it's identical to column.ilike('%' + str + '%')


 since we do have ilike() as an operator icontains() would be 
 appropriate at this point (also startswith,endswith).



 3. There is no builtin function (that I found, please correct me if I'm 
 wrong!) for escaping a string being passed to any functions in this family.


 will be 2694


 While I think that column.like and column.ilike should definitely /not/ 
 escape their argument (you know you're trying for a pattern match here, and 
 that you're matching against a pattern), I think that the 
 .contains/.startswith/.endswith family of functions probably should perform 
 this escaping transparently.  Between DBAPI 2.0, SQLAlchemy and 
 parameterized querying I don't need to worry about escaping input, so why 
 should I have to pay attention to that detail when using .contains?  Also, 
 case insensitive versions of the above would probably be useful.

 That said, a proper fix might be complicated since it could inadvertently 
 break existing code that relies on the current behavior of .contains()



 -- Daniel


 -- 
 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+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.comjavascript:
 .
 Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
 For more options, visit https://groups.google.com/groups/opt_out.
  
  




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




Re: [sqlalchemy] EAV Optimizations

2013-05-16 Thread Claudio Freire
On Thu, May 16, 2013 at 7:16 PM, Simon King si...@simonking.org.uk wrote:
 I don't think this would be a good match for HSTORE - I assume that 
 retrieving values from HSTORE won't be as efficient as retrieving them from 
 their own rows.

It depends on the number of attributes per test. It won't ever be as
efficient the access itself, but it might compensate the overhead
having one row per attribute. Furthermore, you can create functional
indexes to index over a particularly interesting attribute, and with
partial indexes you can even filter, which means, it could be pretty
fast if there's no need to run arbitrary queries. I don't think trends
over time would be a problem for an HSTORE-based schema, since you'd
already pay the cost of sequential scan anyway. This is all assuming
there's a limited and rather small number of attributes per test
(dozens?). Otherwise EAV is probably better.

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




Re: [sqlalchemy] textcolumn.contains() escaping, the lack of icontains(), and possible bug?

2013-05-16 Thread Michael Bayer

On May 16, 2013, at 6:22 PM, Bobby Impollonia bob...@gmail.com wrote:

 Sounds like a useful feature.
 
 Regarding case sensitivity, perhaps it would better if each of these methods 
 (even like() and contains()) took a keyword argument along the lines of 
 col.endswith('foo', case_sensitive=False) rather than adding extra methods 
 with weird names like iendswith.

yes I've thought of that, though we already have ilike() for like(), as 
this is a well known Postgresql operator, so I fear this might introduce some 
inconsistency. We'd really need to add case_sensitive to like() as well and 
everywhere, and just have ilike() be a synonym for like(..., 
case_sensitive=False).

Additionally, case_sensitive might need to default to None - in its absence, 
technically we don't know if the underlying database is doing case sensitive 
comparison or not.  Setting it to True means, we will use known 
case-insensitive techniques for the target backend.   

But then what do we do on a backend that doesn't have ilike? do we raise an 
error?   what if some backend already has case-insensitive collation set up ?






 
 On Monday, May 13, 2013 3:44:38 PM UTC-7, Michael Bayer wrote:
 
 On May 13, 2013, at 6:30 PM, Daniel Grace thisgen...@gmail.com wrote:
 
 So today I identified a small bug in my code and then, while trying to 
 resolve it, came to a few realizations:
 
 1. column.contains(str) does not escape characters in str such as % and _.  
 Presumably, column.startswith(str) and column.endswith(str) have the same 
 behavior.
 
 this will be called autoescape and is ticket 2694: 
 http://www.sqlalchemy.org/trac/ticket/2694 .if someone wants to work on a 
 patch for this it would be v. helpful.   It's a little late to turn on the 
 escaping for all users now as it would break existing workarounds.
 
 
 
 2. There is a distinct lack of column.icontains(str), though the current 
 implementation means it's identical to column.ilike('%' + str + '%')
 
 since we do have ilike() as an operator icontains() would be appropriate 
 at this point (also startswith,endswith).
 
 
 
 3. There is no builtin function (that I found, please correct me if I'm 
 wrong!) for escaping a string being passed to any functions in this family.
 
 will be 2694
 
 
 While I think that column.like and column.ilike should definitely /not/ 
 escape their argument (you know you're trying for a pattern match here, and 
 that you're matching against a pattern), I think that the 
 .contains/.startswith/.endswith family of functions probably should perform 
 this escaping transparently.  Between DBAPI 2.0, SQLAlchemy and 
 parameterized querying I don't need to worry about escaping input, so why 
 should I have to pay attention to that detail when using .contains?  Also, 
 case insensitive versions of the above would probably be useful.
 
 That said, a proper fix might be complicated since it could inadvertently 
 break existing code that relies on the current behavior of .contains()
 
 
 -- Daniel
 
 
 -- 
 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+...@googlegroups.com.
 To post to this group, send email to sqlal...@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.
  
  
 
 
 -- 
 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.
  
  

-- 
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] passing additional values to association_proxy's 'creator' method

2013-05-16 Thread Gerald Thibault
I have a User model, and a Group model, and a m2m relation between them.

I also have a proxy on the user that routes directly to the Group 
instances. The creator function, however, only takes one param (group), so 
when I pass in a group, I have no way to look it up to see if the (user_id, 
group_id) combo is in use already, because i only have the group. It seems 
like I am probably missing something very simple, but I can't figure out 
what it is. The code below can be run to show the issue I am having.

The last line, user.groups = [group] , throws an error because 'self' isn't 
defined. self clearly doesn't work here, what would the workaround be to 
get the User instance's id value into that creator function? The group I 
am passing in is the same as the group currently assigned, so rather than 
purging the collection and adding a UserGroup with only a group_id (the 
user_id gets populated later via the relationship, but at that point it is 
too late, because it's already decided the new object is not the same as 
the old, and it purges the old one), i'd like to be able to identify that 
the identity_key is the same, and just let it be.

Code below##

from sqlalchemy import *
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session, relationship, backref


e = create_engine('sqlite:tmp/test.db', echo=False)
Base = declarative_base()
Base.metadata = MetaData(e)


class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)

def usergroup_creator(group):
session = Session(e)
ugroup = session.query(UserGroup) \
.filter_by(user_id=self.id) \
.filter_by(group_id=group.id) \
.first()
if not ugroup:
return UserGroup(group=group)

groups = association_proxy('user_groups', 'group',
creator=usergroup_creator)

class Group(Base):
__tablename__ = 'groups'
id = Column(Integer, primary_key=True)

class UserGroup(Base):
__tablename__ = 'user_groups'
user_id = Column(Integer, ForeignKey(User.id), primary_key=True)
group_id = Column(Integer, ForeignKey(Group.id), primary_key=True)

user = relationship(User, backref='user_groups')
group = relationship(Group, backref='user_groups')

if __name__ == '__main__':
Base.metadata.drop_all()
Base.metadata.create_all()

user = User(id=1)
group = Group(id=1)
ugroup = UserGroup(user=user, group=group)

session = Session(e)
session.add(user)
session.add(group)
session.add(ugroup)
session.commit()
session.expunge_all()

user = session.query(User).get(1)
group = session.query(Group).get(1)
user.groups = [group]

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




Re: [sqlalchemy] Relationship configuration that isn't functioning as I expect

2013-05-16 Thread Bobby Impollonia
That makes sense. I am seeing one problem with this approach and it causes 
the asserts in original gist to still fail. The problem is that the 
identity map remembers that I constructed my objects as instances of the 
parent class even across commit and expire boundaries. So the following 
assert fails:

street_affiliation = Affiliation(user=user, address_type='street', 
address_id=1)
session.add(street_affiliation)
session.flush()
session.commit()
street_affiliation = 
session.query(Affiliation).filter_by(address_type='street').one()
assert isinstance(street_affiliation, StreetAffiliation)

And as a result the asserts in the original gist still fail.

I understand why this happens (the identity map uses weakrefs but there is 
a still a reference to the old object of type Affiliation) and how to work 
around it (delete the reference to the old affiliation before querying or 
construct the affiliation object as a StreetAffiliation instead of as an 
Affiliation). 
It is still somewhat surprising since I am used to assuming that once a 
commit/ expire_all has happened, fetching from the database will give the 
right results, but in this case the affiliation I fetch after the 
flush incorrectly tells me that its street_address is None.

However, I don't see this being a problem in production and I think this 
will work for our application. Thanks.

On Thursday, May 16, 2013 12:49:17 PM UTC-7, Michael Bayer wrote:


 On May 16, 2013, at 3:02 PM, Bobby  Impollonia 
 bob...@gmail.comjavascript: 
 wrote: 

  
  I hoped to end up with something like: 
  SELECT email_addresses.id AS email_addresses_id, 
 email_addresses.address AS email_addresses_address 
  FROM email_addresses, affiliations 
  WHERE affiliations.address_type = 'email' AND affiliations.address_id = 
 email_addresses.id AND affiliations.id = 1 
  
  Two questions: 
  1) Is the behavior I am seeing here expected given my relationship 
 configuration? 
  2) How can I configure my relationship to exhibit the desired behavior 
 in the situation shown above? 

 Ok well lets think of it in terms of joins.  What if you wanted to load 
 all the affiliations and EmailAddresses together?  the join would be: 

 select * from affiliations JOIN email_addresses ON affiliations.address_id=
 email_addresses.id AND affiliations.address_type='email' 

 above, there's not really a space for AND affiliations.id = ...something 
 ?, unless maybe if it were equated to itself. 

 So maybe, this kind of thing would be possible if you could say: 

 email_address = relationship( 
 'EmailAddress', 
 primaryjoin=and_(address_type == 'email', 
 id == lazy(id), 
  address_id  == EmailAddress.id), 
 foreign_keys=[address_id], 
 viewonly=True) 

 the lazy load would need to figure out to set up a bind for one of the 
 slot there (that's the hypothetical lazy() annotation).   its funny we're 
 a lot closer to that sort of thing, since we do have situations where we 
 have things like column == remote(column) now, but not quite in that 
 arrangement. 

 But I don't think we need to get into any of that here since your class 
 has a discriminator anyway, we can just use inheritance so that your 
 different Affiliation objects know what to do, see below. 


 #!/usr/bin/env python 
 from sqlalchemy import Column, Integer, String, ForeignKey, create_engine, 
 and_ 
 from sqlalchemy.ext.declarative import declarative_base 
 from sqlalchemy.orm import sessionmaker, relationship, backref, 
 contains_eager, remote 

 engine = create_engine('sqlite:///:memory:', echo=True) 
 Session = sessionmaker(bind=engine) 
 session = Session() 
 Base = declarative_base() 

 class User(Base): 
 __tablename__ = 'users' 
 id = Column(Integer, primary_key=True) 


 class StreetAddress(Base): 
 __tablename__ = 'steet_addresses' 
 id = Column(Integer, primary_key=True) 
 address = Column(String, nullable=False) 


 class EmailAddress(Base): 
 __tablename__ = 'email_addresses' 
 id = Column(Integer, primary_key=True) 
 address = Column(String, nullable=False) 


 class Affiliation(Base): 
 __tablename__ = 'affiliations' 
 id = Column(Integer, primary_key=True) 
 user_id = Column(Integer, ForeignKey('users.id'), nullable = False) 
 address_type = Column(String, nullable=False) 
 address_id = Column(Integer, nullable=False) 

 user = relationship(User, backref='affiliations') 

 street_address = None 
 email_address = None 

 __mapper_args__ = dict(polymorphic_on=address_type) 

 class EmailAffiliation(Affiliation): 

 email_address = relationship( 
 'EmailAddress', 
 primaryjoin=Affiliation.address_id  == EmailAddress.id, 
 foreign_keys=[Affiliation.address_id], 
 viewonly=True) 
 __mapper_args__ = dict(polymorphic_identity='email') 

 class StreetAffiliation(Affiliation): 

 street_address = relationship( 
 

Re: [sqlalchemy] Relationship configuration that isn't functioning as I expect

2013-05-16 Thread Michael Bayer

On May 16, 2013, at 9:17 PM, Bobby Impollonia bob...@gmail.com wrote:

 That makes sense. I am seeing one problem with this approach and it causes 
 the asserts in original gist to still fail. The problem is that the identity 
 map remembers that I constructed my objects as instances of the parent class 
 even across commit and expire boundaries. So the following assert fails:
 
 street_affiliation = Affiliation(user=user, address_type='street', 
 address_id=1)

right well you don't do that anymore ;)  make it StreetAffiliation.  Or use a 
factory method like Affiliation.create(type=street), or add a special __new__ 
to Affiliation to do the same thing.

 
 I understand why this happens (the identity map uses weakrefs but there is a 
 still a reference to the old object of type Affiliation) and how to work 
 around it (delete the reference to the old affiliation before querying or 
 construct the affiliation object as a StreetAffiliation instead of as an 
 Affiliation). It is still somewhat surprising since I am used to assuming 
 that once a commit/ expire_all has happened, fetching from the database will 
 give the right results, but in this case the affiliation I fetch after the 
 flush incorrectly tells me that its street_address is None.

the expire removes the contents of __dict__ of all the objects, but not the 
objects themselves, which means their type is also preserved in the session.   
The objects will fall out of the session if you lose all references to them on 
the outside, but that is also assuming they are garbage collected which won't 
necessarily be immediate if there are any cycles.


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