[sqlalchemy] 0.8.x - can't get correlation to work with nested subquery in column property

2013-06-05 Thread Yap Sok Ann
I am getting stuck trying to upgrade to 0.8.x, as I can't get correlation 
to work with nested subquery in column property. Here's a slightly absurd 
example for illustration:

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

Base = declarative_base()

class Phone(Base):
__tablename__ = 'phones'

id = Column(Integer, primary_key=True)
number = Column(String(20))
contact_id = Column(Integer, ForeignKey('contacts.id'))
contact = relationship('Contact', backref='phones')

class Contact(Base):
__tablename__ = 'contacts'

id = Column(Integer, primary_key=True)
name = Column(String(200))

t = select(
[Phone.number.label('value')],
Phone.contact_id == Contact.id,
).correlate(Contact.__table__).alias('t')

Contact.phone_numbers = column_property(
select(
[func.string_agg(t.c.value, ', ')],
).as_scalar().label('phone_numbers'),
deferred=True,
)

session = Session()

print session.query(Contact).order_by(Contact.phone_numbers)


0.7.x:
SELECT contacts.id AS contacts_id, contacts.name AS contacts_name 
FROM contacts ORDER BY (SELECT string_agg(t.value, :string_agg_2) AS 
string_agg_1 
FROM (SELECT phones.number AS value 
FROM phones 
WHERE phones.contact_id = contacts.id) AS t)

0.8.x:
SELECT contacts.id AS contacts_id, contacts.name AS contacts_name 
FROM contacts ORDER BY (SELECT string_agg(t.value, :string_agg_2) AS 
string_agg_1 
FROM (SELECT phones.number AS value 
FROM phones, contacts 
WHERE phones.contact_id = contacts.id) AS t)


I tried `correlate_except` but it doesn't work in this case either. Perhaps 
a side effect from ticket:2668?

-- 
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: Changing a value linked with a one-to-one relationship

2013-06-05 Thread Etienne Rouxel
Hello Michael

Sorry for the late reply.

So, below is my full stack trace:

Traceback (most recent call last):
  File 
/Users/foobar/Developpement/nursery_project/applications/nurserydb/utils_scripts/test2.py,
 
line 64, in module
plant.taxon = taxon_new  # triggers an IntegrityError
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/attributes.py, 
line 303, in __set__
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/attributes.py, 
line 804, in set
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/attributes.py, 
line 824, in fire_replace_event
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/attributes.py, 
line 1131, in emit_backref_from_scalar_set_event
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/attributes.py, 
line 638, in append
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/attributes.py, 
line 788, in set
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/attributes.py, 
line 613, in get
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/strategies.py, 
line 524, in _load_for_state
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/strategies.py, 
line 585, in _emit_lazyload
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/query.py, line 
2104, in all
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/query.py, line 
2215, in __iter__
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/session.py, line 
1138, in _autoflush
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/session.py, line 
1817, in flush
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/session.py, line 
1935, in _flush
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/util/langhelpers.py, 
line 58, in __exit__
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/session.py, line 
1899, in _flush
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/unitofwork.py, 
line 372, in execute
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/unitofwork.py, 
line 525, in execute
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/persistence.py, 
line 58, in save_obj
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/orm/persistence.py, 
line 491, in _emit_update_statements
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/engine/base.py, line 
662, in execute
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/engine/base.py, line 
761, in _execute_clauseelement
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/engine/base.py, line 
874, in _execute_context
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/engine/base.py, line 
1024, in _handle_dbapi_exception
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/util/compat.py, line 
163, in raise_from_cause
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/engine/base.py, line 
867, in _execute_context
  File build/bdist.macosx-10.6-x86_64/egg/sqlalchemy/engine/default.py, 
line 324, in do_execute
sqlalchemy.exc.IntegrityError: (IntegrityError) null value in column 
taxon_id violates not-null constraint
 'UPDATE botany.plant SET taxon_id=%(taxon_id)s WHERE botany.plant.id = 
%(botany_plant_id)s' {'taxon_id': None, 'botany_plant_id': -2147483643}


I guess it correspond to what you mentioned.

I have tried to use what you told :

with session.no_autoflush:
plant.taxon = taxon_new

...and it works fine.

But the thing is that I don't need it in case I comment out the line :

taxon_old = session.query(Taxon).get(-2147483634)

and the test:

print plant.taxon is taxon_old  # True


It seems that the problems occurs because the taxon_old is already loaded 
in the identity map so the taxon.plant of the already loaded taxon_old must 
be changed to reflect the change made by the below line:

plant.taxon = taxon_new  # triggers an IntegrityError

This is totally understandable.

However, I get confused by SQLAlchemy trying to set taxon_id to NULL or 
even worse, by SQLAlchemy trying to delete the plant if I configure a 
cascade='all, delete-orphan' on the backref side of the relationship. I 
understand that it might not be easy for SQLAlchemy to understand what I 
am trying to do, but the fact that I end up with two different results 
depending on whether or not taxon_old is previously loaded is confusing.


Anyway, SQLAlchemy is still very impressive and never ceases to amaze me 
every day I discover new features. Thank you for that.



Le mardi 4 juin 2013 16:38:30 UTC+2, Etienne Rouxel a écrit :

 Hello

 I would like to change a value in a one-to-one relationship but I cannot 
 because of some actions that SQLAlchemy try to do, and I don't know why.
 Here is my simplified code :

 # -*- coding: utf-8 -*-
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import declarative_base

 Base = declarative_base()

 _taxon_table = Table('taxon', Base.metadata,
 Column('id', Integer, primary_key=True),
 schema='botany'
 )

 _foliagetype_table = Table('foliagetype', Base.metadata,
 

Re: [sqlalchemy] [Q][SA 0.7.9] yield_per() vs. joinedload() and subqueryload()

2013-06-05 Thread Ladislav Lenart
Hello.

I have one more question about my approach to WindowedRangeQuery:

 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
  * It has no options.
* Can I reset the options with q = q.options(None)?
  * It has select with the over by magic taken from WindowedRangeQuery recipe.
* I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q and
 execute it in a loop.

Suppose I have a complex query (without options() / order_by()) to obtain the
objects I want. I use this query to calculate window intervals. I don't have to
use it again to fetch the objects, because I already have their id intervals. Am
I right?


Thank you,

Ladislav Lenart


On 4.6.2013 19:15, Ladislav Lenart wrote:
 On 4.6.2013 18:49, Michael Bayer wrote:

 On Jun 4, 2013, at 12:28 PM, Ladislav Lenart lenart...@volny.cz wrote:


 Absolutely, you should do whatever you have to in order to get the range
 you want, in fact the recipe even says this...

 Ok. What I want to do is basically the following:
 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
  * It has no options.
* Can I reset the options with q = q.options(None)?
  * It has select with the over by magic taken from WindowedRangeQuery 
 recipe.
* I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q and
 execute it in a loop.

 Can this strategy work?

 there's not a publicly supported feature to reset the options right now so 
 you'd probably need to apply them after you get your window ranging query.   
You can probably remove the effect of eager loaders if you were to just 
 assign a blank _attributes dictionary to the new query though (just no long 
 term guarantees).

 other than that, I use the windowing concept extensively and it works very 
 well.
 
 Ok, I will try it.
 
 Thank you very much for your invaluable insights,
 
 Ladislav Lenart

-- 
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] [Q][SA 0.7.9] yield_per() vs. joinedload() and subqueryload()

2013-06-05 Thread Ladislav Lenart
Hello.

I've tried an experiment to verify that yield_per() with subqueryload() behaves
as badly as you described, but according to my practical observation, it issues
ONE subqueryload() and everything behaves as I would expect. It emits two
SELECTs, one to fetch the objects and the second one to fetch the related data
and that's about it, see below. So back to square one, what is wrong with it?


Base = declarative_base()

class Contact(Base):
# Just a sketch, I hope you get the picture.
id,
name,
phones = relationship(Phone) # many

class Phone(Base):
# Just a sketch, I hope you get the picture.
id,
number,
contact = relationship(Contact) # one

# Setup engine with echo set to True.

phones = ['123456789', '987654321', '555777999']
for i in range(1, 11):
c = Contact(name=u' '.join([u'Contact', unicode(i)]))
session.add(c)
session.add_all(Phone(contact=c, number=e) for e in phones)
session.flush()
session.expunge_all()

q = session.query(Contact).options(subqueryload(Contact.phones))
for each in q.yield_per(2):
print each.last_name
for e in each.phones:
print e

The output is like this:
SA info about all the inserts after session.flush().
SA info about select for contacts.
SA info about select for their phones.
Contact 10
123456789
987654321
555777999
Contact 9
123456789
987654321
555777999
Contact 8
123456789
987654321
555777999
Contact 7
123456789
987654321
555777999
Contact 6
123456789
987654321
555777999
Contact 5
123456789
987654321
555777999
Contact 4
123456789
987654321
555777999
Contact 3
123456789
987654321
555777999
Contact 2
123456789
987654321
555777999
Contact 1
123456789
987654321
555777999


Thank you,

Ladislav Lenart


On 5.6.2013 11:26, Ladislav Lenart wrote:
 Hello.
 
 I have one more question about my approach to WindowedRangeQuery:
 
 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
  * It has no options.
* Can I reset the options with q = q.options(None)?
  * It has select with the over by magic taken from WindowedRangeQuery recipe.
* I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q and
 execute it in a loop.
 
 Suppose I have a complex query (without options() / order_by()) to obtain the
 objects I want. I use this query to calculate window intervals. I don't have 
 to
 use it again to fetch the objects, because I already have their id intervals. 
 Am
 I right?
 
 
 Thank you,
 
 Ladislav Lenart
 
 
 On 4.6.2013 19:15, Ladislav Lenart wrote:
 On 4.6.2013 18:49, Michael Bayer wrote:

 On Jun 4, 2013, at 12:28 PM, Ladislav Lenart lenart...@volny.cz wrote:


 Absolutely, you should do whatever you have to in order to get the range
 you want, in fact the recipe even says this...

 Ok. What I want to do is basically the following:
 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
  * It has no options.
* Can I reset the options with q = q.options(None)?
  * It has select with the over by magic taken from WindowedRangeQuery 
 recipe.
* I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q 
 and
 execute it in a loop.

 Can this strategy work?

 there's not a publicly supported feature to reset the options right now 
 so you'd probably need to apply them after you get your window ranging 
 query.  You can probably remove the effect of eager loaders if you were 
 to just assign a blank _attributes dictionary to the new query though (just 
 no long term guarantees).

 other than that, I use the windowing concept extensively and it works very 
 well.

 Ok, I will try it.

 Thank you very much for your invaluable insights,

 Ladislav Lenart

-- 
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] Specifying foreign_keys and remote_side in self-referential many-to-many relationship

2013-06-05 Thread Hong Minhee
Hi,

I have two tables User and Following, and User has two relationships followings 
and followers.  It’s so typical, and next I want is readonly relationship to 
union of followings and followers.  I tried like:

friends = relationship(
'User',
collection_class=set,
primaryjoin='''or_(
and_(foreign(User.id) == Following.follower_id,
 remote(User.id) == Following.followee_id),
and_(foreign(User.id) == Following.followee_id,
 remote(User.id) == Following.follower_id)
)''',
viewonly=True
)

but it seems to no work because foreign_keys and remote_side are the same 
columns (User.id).  The error message is:

sqlalchemy.exc.ArgumentError: Can't determine relationship direction for 
relationship 'User.friends' - foreign key columns within the join condition are 
present in both the parent and the child's mapped tables.  Ensure that only 
those columns referring to a parent column are marked as foreign, either via 
the foreign() annotation or via the foreign_keys argument.

Basically I want to find how to specify foreign_keys and remote_side in such 
self-referential many-to-many relationships, but it’s okay if there’re any 
other ways to implement the same thing.  I just need to use such relationship 
in query expressions e.g. query.filter(User.friends.any(…)), 
query.options(joinedload(User.friends)) and instance properties e.g. 
map(make_json, user.friends).  (If I implement it using @property decorator it 
won’t work with query expressions.)

I read these two chapters in the docs:


http://docs.sqlalchemy.org/en/rel_0_8/orm/relationships.html#self-referential-many-to-many-relationship

http://docs.sqlalchemy.org/en/rel_0_8/orm/relationships.html#creating-custom-foreign-conditions

Are there any other resources to get more hints about it?

Thanks,
Hong Minhee

-- 
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: Specifying foreign_keys and remote_side in self-referential many-to-many relationship

2013-06-05 Thread Hong Minhee
It seems I found the most close solution:

http://stackoverflow.com/a/9119764/383405

I haven’t been aware that secondary can take select() query as well.

Might there be another way to achieve the same by any chance?

On Jun 5, 2013, at 9:27 PM, Hong Minhee min...@dahlia.kr wrote:

 Hi,
 
 I have two tables User and Following, and User has two relationships 
 followings and followers.  It’s so typical, and next I want is readonly 
 relationship to union of followings and followers.  I tried like:
 
friends = relationship(
'User',
collection_class=set,
primaryjoin='''or_(
and_(foreign(User.id) == Following.follower_id,
 remote(User.id) == Following.followee_id),
and_(foreign(User.id) == Following.followee_id,
 remote(User.id) == Following.follower_id)
)''',
viewonly=True
)
 
 but it seems to no work because foreign_keys and remote_side are the same 
 columns (User.id).  The error message is:
 
sqlalchemy.exc.ArgumentError: Can't determine relationship direction for 
 relationship 'User.friends' - foreign key columns within the join condition 
 are present in both the parent and the child's mapped tables.  Ensure that 
 only those columns referring to a parent column are marked as foreign, either 
 via the foreign() annotation or via the foreign_keys argument.
 
 Basically I want to find how to specify foreign_keys and remote_side in such 
 self-referential many-to-many relationships, but it’s okay if there’re any 
 other ways to implement the same thing.  I just need to use such relationship 
 in query expressions e.g. query.filter(User.friends.any(…)), 
 query.options(joinedload(User.friends)) and instance properties e.g. 
 map(make_json, user.friends).  (If I implement it using @property decorator 
 it won’t work with query expressions.)
 
 I read these two chapters in the docs:
 

 http://docs.sqlalchemy.org/en/rel_0_8/orm/relationships.html#self-referential-many-to-many-relationship

 http://docs.sqlalchemy.org/en/rel_0_8/orm/relationships.html#creating-custom-foreign-conditions
 
 Are there any other resources to get more hints about it?
 
 Thanks,
 Hong Minhee

-- 
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] [Q][SA 0.7.9] yield_per() vs. joinedload() and subqueryload()

2013-06-05 Thread Ladislav Lenart
Hello.

One more note. I've just tried the below experiment with joinedload() instead of
subqueryload() and that does NOT work just as you expected. One contact is
returned several times and the first occurrences have incomplete phones.

However my experiments with subqueryload() suggest that it works just fine with
yield_per(). Can you elaborate on that one please?


Thank you,

Ladislav Lenart


On 5.6.2013 14:03, Ladislav Lenart wrote:
 Hello.
 
 I've tried an experiment to verify that yield_per() with subqueryload() 
 behaves
 as badly as you described, but according to my practical observation, it 
 issues
 ONE subqueryload() and everything behaves as I would expect. It emits two
 SELECTs, one to fetch the objects and the second one to fetch the related data
 and that's about it, see below. So back to square one, what is wrong with it?
 
 
 Base = declarative_base()
 
 class Contact(Base):
 # Just a sketch, I hope you get the picture.
 id,
 name,
 phones = relationship(Phone) # many
 
 class Phone(Base):
 # Just a sketch, I hope you get the picture.
 id,
 number,
 contact = relationship(Contact) # one
 
 # Setup engine with echo set to True.
 
 phones = ['123456789', '987654321', '555777999']
 for i in range(1, 11):
 c = Contact(name=u' '.join([u'Contact', unicode(i)]))
 session.add(c)
 session.add_all(Phone(contact=c, number=e) for e in phones)
 session.flush()
 session.expunge_all()
 
 q = session.query(Contact).options(subqueryload(Contact.phones))
 for each in q.yield_per(2):
 print each.last_name
 for e in each.phones:
 print e
 
 The output is like this:
 SA info about all the inserts after session.flush().
 SA info about select for contacts.
 SA info about select for their phones.
 Contact 10
 123456789
 987654321
 555777999
 Contact 9
 123456789
 987654321
 555777999
 Contact 8
 123456789
 987654321
 555777999
 Contact 7
 123456789
 987654321
 555777999
 Contact 6
 123456789
 987654321
 555777999
 Contact 5
 123456789
 987654321
 555777999
 Contact 4
 123456789
 987654321
 555777999
 Contact 3
 123456789
 987654321
 555777999
 Contact 2
 123456789
 987654321
 555777999
 Contact 1
 123456789
 987654321
 555777999
 
 
 Thank you,
 
 Ladislav Lenart
 
 
 On 5.6.2013 11:26, Ladislav Lenart wrote:
 Hello.

 I have one more question about my approach to WindowedRangeQuery:

 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
  * It has no options.
* Can I reset the options with q = q.options(None)?
  * It has select with the over by magic taken from WindowedRangeQuery 
 recipe.
* I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q and
 execute it in a loop.

 Suppose I have a complex query (without options() / order_by()) to obtain the
 objects I want. I use this query to calculate window intervals. I don't have 
 to
 use it again to fetch the objects, because I already have their id 
 intervals. Am
 I right?


 Thank you,

 Ladislav Lenart


 On 4.6.2013 19:15, Ladislav Lenart wrote:
 On 4.6.2013 18:49, Michael Bayer wrote:

 On Jun 4, 2013, at 12:28 PM, Ladislav Lenart lenart...@volny.cz wrote:


 Absolutely, you should do whatever you have to in order to get the range
 you want, in fact the recipe even says this...

 Ok. What I want to do is basically the following:
 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
  * It has no options.
* Can I reset the options with q = q.options(None)?
  * It has select with the over by magic taken from WindowedRangeQuery 
 recipe.
* I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q 
 and
 execute it in a loop.

 Can this strategy work?

 there's not a publicly supported feature to reset the options right now 
 so you'd probably need to apply them after you get your window ranging 
 query.  You can probably remove the effect of eager loaders if you 
 were to just assign a blank _attributes dictionary to the new query though 
 (just no long term guarantees).

 other than that, I use the windowing concept extensively and it works very 
 well.

 Ok, I will try it.

 Thank you very much for your invaluable insights,

 Ladislav Lenart

-- 
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] [Q][SA 0.7.9] yield_per() vs. joinedload() and subqueryload()

2013-06-05 Thread Michael Bayer


the Query emitted by subqueryload does not use yield_per.  so if your total 
result set is 1000 rows, and the total rows represented by all the collections 
is 1,  the first time that query is emitted, 1 rows will be fully 
loaded and processed into memory at once.  This would occur typically somewhere 
in the first few rows of your 50 -row yield_per batch.   So the intent of 
yield_per, which is to conserve memory and upfront loading overhead, would be 
defeated entirely by this.

The subqueryload is emitting once if I recall correctly because I probably at 
some point have the query result being memoized in the query context to prevent 
it from being emitted many times in a yield_per scenario.


On Jun 5, 2013, at 10:20 AM, Ladislav Lenart lenart...@volny.cz wrote:

 Hello.
 
 One more note. I've just tried the below experiment with joinedload() instead 
 of
 subqueryload() and that does NOT work just as you expected. One contact is
 returned several times and the first occurrences have incomplete phones.
 
 However my experiments with subqueryload() suggest that it works just fine 
 with
 yield_per(). Can you elaborate on that one please?
 
 
 Thank you,
 
 Ladislav Lenart
 
 
 On 5.6.2013 14:03, Ladislav Lenart wrote:
 Hello.
 
 I've tried an experiment to verify that yield_per() with subqueryload() 
 behaves
 as badly as you described, but according to my practical observation, it 
 issues
 ONE subqueryload() and everything behaves as I would expect. It emits two
 SELECTs, one to fetch the objects and the second one to fetch the related 
 data
 and that's about it, see below. So back to square one, what is wrong with it?
 
 
 Base = declarative_base()
 
 class Contact(Base):
# Just a sketch, I hope you get the picture.
id,
name,
phones = relationship(Phone) # many
 
 class Phone(Base):
# Just a sketch, I hope you get the picture.
id,
number,
contact = relationship(Contact) # one
 
 # Setup engine with echo set to True.
 
 phones = ['123456789', '987654321', '555777999']
 for i in range(1, 11):
c = Contact(name=u' '.join([u'Contact', unicode(i)]))
session.add(c)
session.add_all(Phone(contact=c, number=e) for e in phones)
 session.flush()
 session.expunge_all()
 
 q = session.query(Contact).options(subqueryload(Contact.phones))
 for each in q.yield_per(2):
print each.last_name
for e in each.phones:
print e
 
 The output is like this:
 SA info about all the inserts after session.flush().
 SA info about select for contacts.
 SA info about select for their phones.
 Contact 10
 123456789
 987654321
 555777999
 Contact 9
 123456789
 987654321
 555777999
 Contact 8
 123456789
 987654321
 555777999
 Contact 7
 123456789
 987654321
 555777999
 Contact 6
 123456789
 987654321
 555777999
 Contact 5
 123456789
 987654321
 555777999
 Contact 4
 123456789
 987654321
 555777999
 Contact 3
 123456789
 987654321
 555777999
 Contact 2
 123456789
 987654321
 555777999
 Contact 1
 123456789
 987654321
 555777999
 
 
 Thank you,
 
 Ladislav Lenart
 
 
 On 5.6.2013 11:26, Ladislav Lenart wrote:
 Hello.
 
 I have one more question about my approach to WindowedRangeQuery:
 
 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
 * It has no options.
   * Can I reset the options with q = q.options(None)?
 * It has select with the over by magic taken from WindowedRangeQuery 
 recipe.
   * I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q 
 and
 execute it in a loop.
 
 Suppose I have a complex query (without options() / order_by()) to obtain 
 the
 objects I want. I use this query to calculate window intervals. I don't 
 have to
 use it again to fetch the objects, because I already have their id 
 intervals. Am
 I right?
 
 
 Thank you,
 
 Ladislav Lenart
 
 
 On 4.6.2013 19:15, Ladislav Lenart wrote:
 On 4.6.2013 18:49, Michael Bayer wrote:
 
 On Jun 4, 2013, at 12:28 PM, Ladislav Lenart lenart...@volny.cz wrote:
 
 
 Absolutely, you should do whatever you have to in order to get the range
 you want, in fact the recipe even says this...
 
 Ok. What I want to do is basically the following:
 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
 * It has no options.
   * Can I reset the options with q = q.options(None)?
 * It has select with the over by magic taken from WindowedRangeQuery 
 recipe.
   * I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q 
 and
 execute it in a loop.
 
 Can this strategy work?
 
 there's not a publicly supported feature to reset the options right now 
 so you'd probably need to apply them after you get your window ranging 
 query.  You can probably remove the effect of eager loaders 

Re: [sqlalchemy] Re: Changing a value linked with a one-to-one relationship

2013-06-05 Thread Michael Bayer

On Jun 5, 2013, at 3:52 AM, Etienne Rouxel rouxel.etie...@gmail.com wrote:

 
 However, I get confused by SQLAlchemy trying to set taxon_id to NULL or even 
 worse,

please keep in mind that this was within an autoflush, in between where the 
state of your object graph in memory was complete.  If the flush were to 
succeed, upon the next flush the row would be updated again to the correct 
value.   This is why its important that autoflush run within a transaction.


 by SQLAlchemy trying to delete the plant if I configure a cascade='all, 
 delete-orphan' on the backref side of the relationship. I understand that it 
 might not be easy for SQLAlchemy to understand what I am trying to do, but 
 the fact that I end up with two different results depending on whether or not 
 taxon_old is previously loaded is confusing.

one-to-one relationships have problems in this area, and I can also show you 
versions of your test where a single Taxon gets more than one Plant assigned to 
it, which would then return more than one row for that relationship (SQLAlchemy 
emits a warning when this condition is detected).That's really the main 
concern in this area - SQLAlchemy's load in this case is to detect this 
condition but it can be defeated.




-- 
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] [Q][SA 0.7.9] yield_per() vs. joinedload() and subqueryload()

2013-06-05 Thread Ladislav Lenart
Ok, so yield_per() is useless when subqueryload() is used.

Thank you,

Ladislav Lenart


On 5.6.2013 16:27, Michael Bayer wrote:
 the Query emitted by subqueryload does not use yield_per.  so if your total 
 result set is 1000 rows, and the total rows represented by all the 
 collections is 1,  the first time that query is emitted, 1 rows will 
 be fully loaded and processed into memory at once.  This would occur 
 typically somewhere in the first few rows of your 50 -row yield_per batch.   
 So the intent of yield_per, which is to conserve memory and upfront loading 
 overhead, would be defeated entirely by this.
 
 The subqueryload is emitting once if I recall correctly because I probably at 
 some point have the query result being memoized in the query context to 
 prevent it from being emitted many times in a yield_per scenario.
 
 
 On Jun 5, 2013, at 10:20 AM, Ladislav Lenart lenart...@volny.cz wrote:
 
 Hello.

 One more note. I've just tried the below experiment with joinedload() 
 instead of
 subqueryload() and that does NOT work just as you expected. One contact is
 returned several times and the first occurrences have incomplete phones.

 However my experiments with subqueryload() suggest that it works just fine 
 with
 yield_per(). Can you elaborate on that one please?


 Thank you,

 Ladislav Lenart


 On 5.6.2013 14:03, Ladislav Lenart wrote:
 Hello.

 I've tried an experiment to verify that yield_per() with subqueryload() 
 behaves
 as badly as you described, but according to my practical observation, it 
 issues
 ONE subqueryload() and everything behaves as I would expect. It emits two
 SELECTs, one to fetch the objects and the second one to fetch the related 
 data
 and that's about it, see below. So back to square one, what is wrong with 
 it?


 Base = declarative_base()

 class Contact(Base):
# Just a sketch, I hope you get the picture.
id,
name,
phones = relationship(Phone) # many

 class Phone(Base):
# Just a sketch, I hope you get the picture.
id,
number,
contact = relationship(Contact) # one

 # Setup engine with echo set to True.

 phones = ['123456789', '987654321', '555777999']
 for i in range(1, 11):
c = Contact(name=u' '.join([u'Contact', unicode(i)]))
session.add(c)
session.add_all(Phone(contact=c, number=e) for e in phones)
 session.flush()
 session.expunge_all()

 q = session.query(Contact).options(subqueryload(Contact.phones))
 for each in q.yield_per(2):
print each.last_name
for e in each.phones:
print e

 The output is like this:
 SA info about all the inserts after session.flush().
 SA info about select for contacts.
 SA info about select for their phones.
 Contact 10
 123456789
 987654321
 555777999
 Contact 9
 123456789
 987654321
 555777999
 Contact 8
 123456789
 987654321
 555777999
 Contact 7
 123456789
 987654321
 555777999
 Contact 6
 123456789
 987654321
 555777999
 Contact 5
 123456789
 987654321
 555777999
 Contact 4
 123456789
 987654321
 555777999
 Contact 3
 123456789
 987654321
 555777999
 Contact 2
 123456789
 987654321
 555777999
 Contact 1
 123456789
 987654321
 555777999


 Thank you,

 Ladislav Lenart


 On 5.6.2013 11:26, Ladislav Lenart wrote:
 Hello.

 I have one more question about my approach to WindowedRangeQuery:

 * Suppose a complex query q with join(...), filter(...) and options(...).
 * I need to create q2 from q such that:
 * It has no options.
   * Can I reset the options with q = q.options(None)?
 * It has select with the over by magic taken from WindowedRangeQuery 
 recipe.
   * I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original q 
 and
 execute it in a loop.

 Suppose I have a complex query (without options() / order_by()) to obtain 
 the
 objects I want. I use this query to calculate window intervals. I don't 
 have to
 use it again to fetch the objects, because I already have their id 
 intervals. Am
 I right?


 Thank you,

 Ladislav Lenart


 On 4.6.2013 19:15, Ladislav Lenart wrote:
 On 4.6.2013 18:49, Michael Bayer wrote:

 On Jun 4, 2013, at 12:28 PM, Ladislav Lenart lenart...@volny.cz wrote:


 Absolutely, you should do whatever you have to in order to get the 
 range
 you want, in fact the recipe even says this...

 Ok. What I want to do is basically the following:
 * Suppose a complex query q with join(...), filter(...) and 
 options(...).
 * I need to create q2 from q such that:
 * It has no options.
   * Can I reset the options with q = q.options(None)?
 * It has select with the over by magic taken from WindowedRangeQuery 
 recipe.
   * I know I can use with_entities() for this.
 * I will use q2 to obtain the window ranges.
 * I will iterate over the window ranges and apply each to the original 
 q and
 execute it in a loop.

 Can this strategy work?

 there's not a publicly supported feature to reset the options right 
 now so you'd probably need 

Re: [sqlalchemy] Reliable way to read comments from database schema

2013-06-05 Thread Mariano Mara



On 06/04/2013 11:22 PM, Warwick Prince wrote:



On 06/04/2013 10:46 PM, Michael Bayer wrote:

There's a long standing ticket to add support for comments, at least at the DDL 
level.   I don't think anyone has looked into what level of support we get from 
the various backends as far as reflection.

So its something the library has room for, but it's an open item for now.  The 
four-year-old ticket is http://www.sqlalchemy.org/trac/ticket/1546.




On Jun 4, 2013, at 8:33 PM, Warwick Prince warwi...@mushroomsys.com wrote:


Hi Michael

I'm toying with the idea of embedding some metadata into the comments on 
columns and/or the table comment.  Is there a way to reliably read the comment 
from the column definition via reflection across all dialects that would 
support a comment at a column level?   Also, can I read the comment normally 
attached to the table definition?

Thanks
Warwick



If this metadata will be used just in sqlalchemy (or python libraries up in the 
stack), you could use the info parameter when creating columns.


OK - sounds promising.  What actually is the 'info' that it reads/writes?  i.e. 
where is it getting it from/putting it in the DB? (Or does it only reside in 
the Python code?)



It is a dictionary and you can store whatever you want in there (please 
see 
http://docs.sqlalchemy.org/en/rel_0_8/core/schema.html#sqlalchemy.schema.SchemaItem.info 
for more info about it). This information is only available on Python code.



Also, I'd like to +1 the task to reflect the comments with support for as many 
dialects as possible :-)   We have developed a large platform using SQLA as the 
ORM, and as part of the maintenance area we have a generic database manager 
that is intended to allow maintenance, viewing, manual row insertion/deletion 
etc (Like MySQL Workbench et al) that is 100% database agnostic.  Comments are 
missing at the moment which is a shame.



--
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] Including counts in query results

2013-06-05 Thread Charlie Clark

Am 04.06.2013, 04:57 Uhr, schrieb Rob Green robsgr...@gmail.com:


Hello,
I'm having some trouble getting my SQL query to work in SQLAlchemy.
In this example, I want to find out the number of meeting rooms and
bathrooms available to a user.  The user is part of a userGroup, which is
assigned to one building.
The building has many meeting rooms and bathrooms.  My sql query looks  
like:

select user.id,
(select count(*) from meetingRoom where userGroup.buildingCode =
meetingRoom.buildingCode),
(select count(*) from restroom where userGroup.buildingCode =
restroom.buildingCode)
from user
join userGroup
on user.userGroupId = userGroup.userGroupId
I've tried using subqueries:
meetingRoomCount
= session.query(func.count(MeetingRoom.id)).join(UserGroup,
MeeingRoom.buildingId == UserGroup.buildingId).subquery()
bathroomCount = session.query(func.count(Bathroom.id)).join(UserGroup,
Bathroom.buildingId == UserGroup.buildingId).subquery()
session.query(User.id, meetingRoomCount, bathroomCount).first()



But this returns the total number of meeting rooms and bathrooms in the
database, not the ones that are specific to that user.



I feel like I'm missing something simple here, anyone have any ideas?


I think you might have more success if you explicitly alias your counts.

SELECT user.id, mr.total, rr.total
FROM
user,
(select count(*) AS total from meetingRoom where userGroup.buildingCode =
 meetingRoom.buildingCode) AS mr,
(select count(*) AS total from restroom where userGroup.buildingCode =
 restroom.buildingCode) AS rr

from user
join userGroup
on user.userGroupId = userGroup.userGroupId

Charlie
--
Charlie Clark
Managing Director
Clark Consulting  Research
German Office
Kronenstr. 27a
Düsseldorf
D- 40217
Tel: +49-211-600-3657
Mobile: +49-178-782-6226

--
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] Retrieve Dates as UTC

2013-06-05 Thread Owen M
Was hunting around for how to do this, and couldn't find any examples, but 
eventually figured it out.

Goal is to have all dates coming out of Postgres to be in UTC, regardless 
of the DBA's timezone configuration.

Key piece of code is as follows:

import sqlalchemy
def set_utc_on_connect(dbapi_con, con_record):
c = dbapi_con.cursor()
c.execute(SET TIME ZONE UTC)
c.close()
sqlalchemy.event.listen(sqlalchemy.pool.Pool, 'connect', set_utc_on_connect)

Now all connections in the pool will have their timezone set to UTC, so all 
queries will return UTC for datetime objects with timezone specified.

Just posting it here incase someone else needed the info.

Cheers,
~Owen

-- 
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] Retrieve Dates as UTC

2013-06-05 Thread Michael Bayer
we do this (for PG and SQL Server):

class utcnow(expression.FunctionElement):
key = 'utcnow'
type = DateTime()

@compiles(utcnow, 'postgresql')
def _pg_utcnow(element, compiler, **kw):
return TIMEZONE('utc', CURRENT_TIMESTAMP)

@compiles(utcnow, 'mssql')
def _ms_utcnow(element, compiler, **kw):
return GETUTCDATE()

you then use utcnow() as your SQL expression.

just remembered i put it in the docs too: 
http://docs.sqlalchemy.org/en/rel_0_8/core/compiler.html#utc-timestamp-function



On Jun 5, 2013, at 4:51 PM, Owen M owenm...@gmail.com wrote:

 Was hunting around for how to do this, and couldn't find any examples, but 
 eventually figured it out.
 
 Goal is to have all dates coming out of Postgres to be in UTC, regardless of 
 the DBA's timezone configuration.
 
 Key piece of code is as follows:
 
 import sqlalchemy
 def set_utc_on_connect(dbapi_con, con_record):
 c = dbapi_con.cursor()
 c.execute(SET TIME ZONE UTC)
 c.close()
 sqlalchemy.event.listen(sqlalchemy.pool.Pool, 'connect', set_utc_on_connect)
 
 Now all connections in the pool will have their timezone set to UTC, so all 
 queries will return UTC for datetime objects with timezone specified.
 
 Just posting it here incase someone else needed the info.
 
 Cheers,
 ~Owen
 
 -- 
 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] Connect to SQL Server (with pyodbc) getting error: sqlalchemy.exc.DBAPIError: (Error) ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver

2013-06-05 Thread Victor Reichert
Hello World!
 
This is my first foray into python and SQL Alchemy, and I'm spinning my 
wheels.  I'm running the code below and am able to connect to my DB and 
query data without error.
 
import pyodbc
cnxn = pyodbc.connect('DSN=py_test; Trusted_Connection=Yes')
 
However, when I try 

import sqlalchemy
engine = sqlalchemy.create_engine('mssql+pyodbc://DSN=py_test; 
Trusted_Connection=Yes')
result = engine.execute(SELECT * FROM dbo.test_table)
I receive the following error, I am running python 3.3 on 32 bit Windows 7 
Enterprise
 
Traceback (most recent call last):
  File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 757, in 
_do_get
return self._pool.get(wait, self._timeout)
  File C:\Python33\lib\site-packages\sqlalchemy\util\queue.py, line 166, 
in get
raise Empty
sqlalchemy.util.queue.Empty
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File C:\Python33\lib\site-packages\sqlalchemy\engine\strategies.py, 
line 80, in connect
return dialect.connect(*cargs, **cparams)
  File C:\Python33\lib\site-packages\sqlalchemy\engine\default.py, line 
285, in connect
return self.dbapi.connect(*cargs, **cparams)
pyodbc.Error: ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data 
source name not found and no default driver specified (0) 
(SQLDriverConnect)')
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File 
C:\Users\V114804\workspace\Remetrica_Simulated_ILC_WW_AP_20130520_ELT\Src\Test_DB_Connection.py,
 
line 11, in module
result = engine.execute(SELECT * FROM dbo.test_table)
  File C:\Python33\lib\site-packages\sqlalchemy\engine\base.py, line 
1613, in execute
connection = self.contextual_connect(close_with_result=True)
  File C:\Python33\lib\site-packages\sqlalchemy\engine\base.py, line 
1661, in contextual_connect
self.pool.connect(),
  File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 272, in 
connect
return _ConnectionFairy(self).checkout()
  File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 425, in 
__init__
rec = self._connection_record = pool._do_get()
  File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 777, in 
_do_get
con = self._create_connection()
  File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 225, in 
_create_connection
return _ConnectionRecord(self)
  File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 318, in 
__init__
self.connection = self.__connect()
  File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 368, in 
__connect
connection = self.__pool._creator()
  File C:\Python33\lib\site-packages\sqlalchemy\engine\strategies.py, 
line 87, in connect
) from e
sqlalchemy.exc.DBAPIError: (Error) ('IM002', '[IM002] [Microsoft][ODBC 
Driver Manager] Data source name not found and no default driver specified 
(0) (SQLDriverConnect)') None None
 
I have also tried:
 
import sqlalchemy
 import pyodbc
 
def connect():
pyodbc.connect('DRIVER={SQL 
Server};Server=SDAWWRMSD05;Database=ReMetrica_Results_201207;Trusted_Connection=Yes')
print('Connect Method Created')
created_engine = sqlalchemy.create_engine('mssql://', creator=connect)
created_result = created_engine.execute(SELECT * FROM dbo.test_table)
The definition is called, then the program hangs.
 
If anyone could please give me some advice on how to get around this that 
would be great.  
 
Thank you for your help, please let me know if I can provide any additional 
information.
 
~Victor
 

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