Re: [sqlalchemy] AssertionError When Removing Children For Association Object

2014-01-09 Thread Russell Holloway



 you need to put a cascade rule on Page.user_relationships, such that when 
 you remove a Page_to_User from the collection, it’s marked as deleted, 
 instead of SQLAlchemy setting the page_id foreign key to NULL, which is 
 invalid here b.c. that column is part of the primary key (and hence the 
 error).   Page_to_User can’t exist in the database without being referred 
 to by a Page object since the primary key would be NULL.

 the delete-orphan cascade is introduced at:


 http://docs.sqlalchemy.org/en/rel_0_9/orm/tutorial.html#configuring-delete-delete-orphan-cascade

 and some more information at: 
 http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#deleting-from-collections



Can you help me understand why a cascade rule is needed? I have read the 
documentation you linked to but still have trouble grasping why it is 
needed. I understand it would make sense if I deleted a page, that it 
should cascade on delete to page_to_user because now the FK page_id is no 
longer valid - the page doesn't exist, so it cannot possibly be mapped 
anywhere.

What I'm having trouble understanding is what is cascading from what to 
what when deleting from this page.user_relationships collection. It doesn't 
cascade from page, because I am not deleting any pages, and it doesn't 
cascade from users, because no users are deleted. The only thing being 
deleted is the mapping itself.

In the database table definition, there doesn't have to be any cascade 
settings at all for the constraints and it will still work fine. Maybe it's 
purely a SQLAlchemy thing and how it's designed for some reason? I would 
just like to understand better for future development. Thanks in advance.

-Russ

-- 
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.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] SQLAlchemy 0.9.1 released

2014-01-09 Thread Michael Bayer

On Jan 8, 2014, at 8:55 PM, limodou limo...@gmail.com wrote:

 
 Yes, I saw the code about 0.8.X and 0.9.1, the None convertion are the same. 
 But difference between them is in AND process. So this inconsistent that 
 you mean it's a bug in 0.8?

it’s a bug in 0.8, yes.

 
 I think raise exception maybe better, so that it'll let user to know what 
 wrong with the condition. Otherwise some code like condition  None can run 
 in 0.8.X very well, but in 0.9 it'll only return nothing without any error 
 thrown at all. It will break the old code.

well we can’t change 0.8 to raise, so raising an exception in 0.9 wouldn’t 
solve much as far as cross-compatibility.   I don’t think this pattern is that 
common in any case.






signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] AssertionError When Removing Children For Association Object

2014-01-09 Thread Michael Bayer

On Jan 9, 2014, at 10:02 AM, Russell Holloway russ.d.hollo...@gmail.com wrote:

 
 you need to put a cascade rule on Page.user_relationships, such that when you 
 remove a Page_to_User from the collection, it’s marked as deleted, instead of 
 SQLAlchemy setting the page_id foreign key to NULL, which is invalid here 
 b.c. that column is part of the primary key (and hence the error).   
 Page_to_User can’t exist in the database without being referred to by a Page 
 object since the primary key would be NULL.
 
 the delete-orphan cascade is introduced at:
 
 http://docs.sqlalchemy.org/en/rel_0_9/orm/tutorial.html#configuring-delete-delete-orphan-cascade
 
 and some more information at: 
 http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#deleting-from-collections
 
 
 
 Can you help me understand why a cascade rule is needed? I have read the 
 documentation you linked to but still have trouble grasping why it is needed. 
 I understand it would make sense if I deleted a page, that it should cascade 
 on delete to page_to_user because now the FK page_id is no longer valid - the 
 page doesn't exist, so it cannot possibly be mapped anywhere.

OK so, you have:

Page.user_relationships - collection of PageToUser

PageToUser - single User

then, you are saying :

some_page.user_relationships = []
session.flush()

What SQL would you expect this to produce?  After a flush, what would the rows 
in your page_to_user table look like?


 
 What I'm having trouble understanding is what is cascading from what to what 
 when deleting from this page.user_relationships collection. It doesn't 
 cascade from page, because I am not deleting any pages, and it doesn't 
 cascade from users, because no users are deleted.

“delete-orphan” means when an item is removed from a collection, in this case a 
PageToUser object, it is marked as deleted.


 In the database table definition, there doesn't have to be any cascade 
 settings at all for the constraints and it will still work fine.

OK you need to show what “works fine” is - how the Page.user_relationships 
collection can be empty on a particular Page object, yet there are PageToUser 
objects in the database which refer to that Page (or if you think the 
PageToUser row still exists, but doesn’t point to any Page, show me how that 
looks).  What’s in the database?




signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] AssertionError When Removing Children For Association Object

2014-01-09 Thread Russell Holloway



 OK so, you have:

 Page.user_relationships - collection of PageToUser

 PageToUser - single User

 then, you are saying :

 some_page.user_relationships = []
 session.flush()

 What SQL would you expect this to produce?  After a flush, what would the 
 rows in your page_to_user table look like?


I would expect it to delete entries, resulting in no rows for that page_id
DELETE FROM Page_To_User WHERE page_id = ?

Perhaps it tries this instead?
UPDATE Page_To_User SET page_id = NULL WHERE page_id = ?

 


 What I'm having trouble understanding is what is cascading from what to 
 what when deleting from this page.user_relationships collection. It doesn't 
 cascade from page, because I am not deleting any pages, and it doesn't 
 cascade from users, because no users are deleted. 


 “delete-orphan” means when an item is removed from a collection, in this 
 case a PageToUser object, it is marked as deleted.


So by default does page.user_relationships call the above UPDATE call and 
set to null or something?
 

 In the database table definition, there doesn't have to be any cascade 
 settings at all for the constraints and it will still work fine. 


 OK you need to show what “works fine” is - how the Page.user_relationships 
 collection can be empty on a particular Page object, yet there are 
 PageToUser objects in the database which refer to that Page (or if you 
 think the PageToUser row still exists, but doesn’t point to any Page, show 
 me how that looks).  What’s in the database?


In my mind, Page.user_relationship is a collection of PageToUser objects, 
so by emptying that collection, all those objects are deleted from 
Page_To_User. It doesn't have anything to do with the Page object itself 
though - only the associations in PageToUser.

The following table definitions work without the CASCADE being used on FK 
at all (it may prevent deletions of Page or User rows due to FK 
constraints, but not in this example since we don't ever delete those rows).

CREATE TABLE Page (
  int page_id not null auto increment,
  varchar(255) title,
  primary key (page_id)
) Engine=InnoDB;

CREATE TABLE User (
  int user_id not null auto increment,
  varchar(255) name,
  primary key (user_id)
) Engine=InnoDB;

CREATE TABLE Page_To_User (
  int page_id not null,
  int user_id not null,
  int relationship_id not null,
  primary key (page_id, user_id, relationship_id),
  foreign key (page_id) references Page(page_id),
  foreign key (user_id) references User(user_id)
) Engine=InnoDB;

Above, there isn't any ON DELETE CASCADE specified for any of the foreign 
keys. My understanding is if there were, 

  foreign key (page_id) references Page(page_id) ON DELETE CASCADE

then, if I delete row with that page_id from Page, then it will cascade 
from Page to Page_To_User and delete the appropriate row. If ON DELETE 
CASCADE is missing, it will complain if I try to delete that Page row, 
because there are FK constraints.

But issuing a simple ' DELETE FROM Page_To_User WHERE page_id = ? ' 
shouldn't require any cascading, at least in SQL. Maybe the cascade keyword 
in SQLAlchemy does not exactly mean cascade on a table definition?

-Russ

-- 
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.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] Multiple inheritance issue

2014-01-09 Thread Enrico Bottani
Hello guys,

I'm building a web service to provide data to our SDK and I'm facing a 
wired problem. I have created 4 different models for my needs, a base class 
that is called *Unit*, two derivatives from the base class *VideoUnit*, 
*QuestionUnit*, and the last class is a derivative of both *VideoUnit* and 
*QuestionUnit*, that is called, with lot of fantasy, *VideoQuestionUnit*.
Everything was working fine till the point I was trying to serialize this 
data to be transmitted with JSON.
I successfully gather JSON from *VideoUnit* and *QuestionUnit *(thanks to 
plaeshttp://stackoverflow.com/questions/7102754/jsonify-a-sqlalchemy-result-set-in-flask)
 
but now I can't figure out why when I try to make the same thing with 
*VideoQuestioUnit 
*the program crash telling me: *KeyError: 'questions'*
I can imagine that there is something wrong when *VideoQuestionUnit* try to 
access the *questions* data declared in *QuestionUnit*(also my dog get 
that I know), but I don't understand what's wrong with that. 
Did someone have an idea of what I'm doing wrong?


*CODE:*
class Unit(db.Model):
id = db.Column(db.Integer, unique = True, primary_key = True)
name = db.Column(db.String(128), index = True, unique = False)
type = db.Column(db.SmallInteger)
brand_id = db.Column(db.Integer, db.ForeignKey('brand.id'))
@property
def serialize(self):
print Serialize on superclass
pass

class VideoUnit(Unit):
uri = db.Column(db.String(256), index = False, unique = False)
@property
def serialize(self):
return {
'ID':   self.id,
'Name'  :   self.name,
'Link'  :   self.uri
}

class QuestionUnit(Unit):
questions = db.relationship('Question', backref = 'QuestionUnit', lazy 
= 'dynamic')
@property
def serialize(self):
return {
'ID':   self.id,
'Name'  :   self.name,
'Questions' :   self.serialize_questions
}
@property
def serialize_questions(self):
return [item.serialize for item in self.questions]

class VideoQuestionUnit(VideoUnit, QuestionUnit):
@property
def serialize(self):
return {
'ID':   self.id,
'Name'  :   self.name,
'Link'  :   self.uri,
'Questions' :   self.serialize_questions
}
@property
def serialize_questions(self):
return [item.serialize for item in self.questions]



Thanks in advance,

Enrico

-- 
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.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] Anybody have twophase/zope.sqlalchemy/MySQL working?

2014-01-09 Thread Jeff Dairiki
Thank you for the reply!  Sorry for the delayed response.  (Holidays.)

On Mon, Dec 23, 2013 at 11:52:25PM -0800, Laurence Rowe wrote:
 On Thursday, 12 December 2013 16:30:59 UTC-8, Jeff Dairiki wrote:
 
  Do you understand why the datamanager is finding the SessionTransaction 
  and using that directly?  (At least I think that's what it's doing --- 
  I haven't sussed this out completely.)  I'm referring to the line from 
  SessionDataManager.__init__: 
 
 self.tx = session.transaction._iterate_parents()[-1] 
 
 
 This is to handle the case of a session being a nested transaction at the 
 time the ``zope.sqlalchemy`` datamanager joins the ``transaction`` 
 transaction
  
 
  and then later the session manager calls .prepare(), .commit() 
  and/or .rollback() on self.tx, *if* self.tx is not None. 
 
  The thing is, for me, if the session has only been used for read 
  operation, 
  self.tx seems to be None.  So the datamanager never commits anything. 
 
  I don't understand (yet) why the data manager doesn't just call 
  .prepare() and .commit() directly on the sqlalchemy session instance. 
 
 
 The zope.sqlalchemy datamanager will rollback the transaction when it 
 detects that no work is done. In that case self.tx is set to None during 
 SessionTransaction.commit and during the two phase commit there is nothing 
 to do.
  
 The sequence in which the datamanager methods are called is found in 
 Transaction._commitResources: 
 https://github.com/zopefoundation/transaction/blob/1.4.1/transaction/_transaction.py#L382
 
 Dunno.  It doesn't seem like it should be MySQL specific thing, but maybe 
  postgres and others are more forgiving of a two-phase XA BEGIN being 
  terminated by a regular one-phase ROLLBACK? 
 
  Anyhow, I'll keep poking when I find a moment.  
 
 
 (And from a later message in this thread)
 
 Okay, so this was not a complete solution.  It does cause the 
  datamanager to commit the the sessions when the transaction is terminated 
  by transaction.commit(), but neither setting the 
  initial state to STATUS_CHANGED, nor calling mark_changed() is enough 
  to get the datamanager to rollback the session if the transaction 
  is ended with transaction.abort(). 
 
 
 Looking at the datamanager logic again, I don't think self.tx can ever be 
 None in abort() (at least not normally) but closing the session will close 
 the underlying transaction on the connection, which issues the rollback: 
 https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_0b1/lib/sqlalchemy/engine/base.py#L1151

Okay, I've traced things out a bit more.

If the session state is not STATUS_INVALIDATED (aka STATUS_CHANGED),
SessionDataManager.commit() does a self._finish('no work').  That is
where self.tx gets set to None (this --- correctly --- then
causes .tpc_vote() and .tpc_finish() to be no-ops.)

So here's the crux of the biscuit: in two-phase-commit mode (at least
with MySQL) the sqlalchemy session (or session transaction) must be either
committed or explicitly rolled back before it is closed.
SessionDataManager.commit() does not do a rollback.

Example code:

import sqlalchemy as sa 

engine = sa.create_engine('mysql://guest@furry/test',
  echo='debug', 
  echo_pool='debug')
Sess = sa.orm.sessionmaker(bind=engine, twophase=True)
sess = Sess()
sess.query(sa.null()).scalar()
#sess.rollback()
sess.close()

Edited log output:

DEBUG:sqlalchemy.pool.QueuePool:Connection _mysql.connection open to 
'furry' at 29a3370 checked out from pool
INFO:sqlalchemy.engine.base.Engine:BEGIN TWOPHASE (implicit)
INFO:sqlalchemy.engine.base.Engine:XA BEGIN %s
INFO:sqlalchemy.engine.base.Engine:('_sa_a38de3b7234d5fe8ad55d2bb13ec195c',)
INFO:sqlalchemy.engine.base.Engine:SELECT NULL AS anon_1
DEBUG:sqlalchemy.pool.QueuePool:Connection _mysql.connection open to 
'furry' at 29a3370 being returned to pool
DEBUG:sqlalchemy.pool.QueuePool:Connection _mysql.connection open to 
'furry' at 29a3370 rollback-on-return
INFO:sqlalchemy.pool.QueuePool:Invalidate connection _mysql.connection 
open to 'furry' at 29a3370 (reason: OperationalError:(1399, 'XAER_RMFAIL: The 
command cannot be executed when global transaction is in the  ACTIVE state'))
DEBUG:sqlalchemy.pool.QueuePool:Closing connection _mysql.connection open 
to 'furry' at 29a3370

Here, no attempt is made to terminate the two-phase (XA) transaction
until the connection is returned to the pool, at which point a
plain one-phase 'ROLLBACK' is issued.  MySQL does not like this,
thus the XAER_RMFAIL error.

Uncommenting the 'sess.rollback()' in the above example results in an
'XA END and 'XA ROLLBACK' being emitted before the connection is
returned to the pool, properly ending the two-phase (XA) transaction.
This eliminates the XAER_RMFAIL error, and results in proper recycling
of the pooled connection.


In zope.sqlalchemy.datamanger, if I change SessionDataManager.commit()
from

Re: [sqlalchemy] AssertionError When Removing Children For Association Object

2014-01-09 Thread Michael Bayer

On Jan 9, 2014, at 10:31 AM, Russell Holloway russ.d.hollo...@gmail.com wrote:

 
 OK so, you have:
 
 Page.user_relationships - collection of PageToUser
 
 PageToUser - single User
 
 then, you are saying :
 
 some_page.user_relationships = []
 session.flush()
 
 What SQL would you expect this to produce?  After a flush, what would the 
 rows in your page_to_user table look like?
 
 
 I would expect it to delete entries, resulting in no rows for that page_id
 DELETE FROM Page_To_User WHERE page_id = ?
 
 Perhaps it tries this instead?
 UPDATE Page_To_User SET page_id = NULL WHERE page_id = ?

You are correct in both cases.So if you follow the instructions for 
delete-orphan cascade as previously mentioned here: 

http://docs.sqlalchemy.org/en/rel_0_9/orm/tutorial.html#configuring-delete-delete-orphan-cascade

the rows will be deleted instead.

Perhaps you’re being thrown off by the fact that an ORM level cascade is set on 
the *opposite* side as a FOREIGN KEY cascade in SQL, but that is how it works.  
  The Page.user_relationships collection is what indicates the handling of 
PageToUser objects.

If you want to see the origin of the “CASCADE” settings, they come from 
Hibernate: 
http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/example-parentchild.html
 .




signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] Multiple inheritance issue

2014-01-09 Thread Michael Bayer

On Jan 9, 2014, at 11:32 AM, Enrico Bottani bei...@mac.com wrote:

 Hello guys,
 
 I'm building a web service to provide data to our SDK and I'm facing a wired 
 problem. I have created 4 different models for my needs, a base class that is 
 called Unit, two derivatives from the base class VideoUnit, QuestionUnit, and 
 the last class is a derivative of both VideoUnit and QuestionUnit, that is 
 called, with lot of fantasy, VideoQuestionUnit.
 Everything was working fine till the point I was trying to serialize this 
 data to be transmitted with JSON.
 I successfully gather JSON from VideoUnit and QuestionUnit (thanks to plaes) 
 but now I can't figure out why when I try to make the same thing with 
 VideoQuestioUnit the program crash telling me: KeyError: 'questions'
 I can imagine that there is something wrong when VideoQuestionUnit try to 
 access the questions data declared in QuestionUnit(also my dog get that I 
 know), but I don't understand what's wrong with that. 
 Did someone have an idea of what I'm doing wrong?

first of all, SQLAlchemy’s inheritance mapping system has no direct support for 
multiple inheritance at all.  True multi-table multiple inheritance in SQL is a 
highly esoteric and complex pattern and I doubt SQLAlchemy is ever going to go 
there, at least fully; just getting single hierarchy inheritance to work fully 
has taken many years and was enormously complicated.   While I see here that at 
least VideoQuestionUnit doesn’t have a table of its own, still the fact that it 
is subclassing two other joined-inh subclasses isn’t something the ORM has any 
idea what to do with.   Loading a VideoQuestionUnit means it would need to join 
to both of the inherited tables, like a polymorphic load does, but there’s no 
mechanism to produce one object deriving from more than one mapped class.  I’m 
surprised the mapping doesn’t just fail immediately.

secondly, well actually I’m not sure there’s a “secondly” here :).   I guess 
the way you can load and persist VideoQuestionUnit objects is by mapping it to 
a JOIN of all three tables at once - and you’d also need to probably add 
“concrete=True” to the mapping so that it doesn’t attempt to use any of the 
superclass mappings for persistence or querying.Not something I’ve tried 
though it might be workable.





 
 
 CODE:
 class Unit(db.Model):
 id = db.Column(db.Integer, unique = True, primary_key = True)
 name = db.Column(db.String(128), index = True, unique = False)
 type = db.Column(db.SmallInteger)
 brand_id = db.Column(db.Integer, db.ForeignKey('brand.id'))
 @property
 def serialize(self):
 print Serialize on superclass
 pass
 
 class VideoUnit(Unit):
 uri = db.Column(db.String(256), index = False, unique = False)
 @property
 def serialize(self):
 return {
 'ID':   self.id,
 'Name'  :   self.name,
 'Link'  :   self.uri
 }
 
 class QuestionUnit(Unit):
 questions = db.relationship('Question', backref = 'QuestionUnit', lazy = 
 'dynamic')
 @property
 def serialize(self):
 return {
 'ID':   self.id,
 'Name'  :   self.name,
 'Questions' :   self.serialize_questions
 }
 @property
 def serialize_questions(self):
 return [item.serialize for item in self.questions]
 
 class VideoQuestionUnit(VideoUnit, QuestionUnit):
 @property
 def serialize(self):
 return {
 'ID':   self.id,
 'Name'  :   self.name,
 'Link'  :   self.uri,
 'Questions' :   self.serialize_questions
 }
 @property
 def serialize_questions(self):
 return [item.serialize for item in self.questions]
 
 
 
 Thanks in advance,
 
 Enrico
 
 -- 
 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.
 For more options, visit https://groups.google.com/groups/opt_out.



signature.asc
Description: Message signed with OpenPGP using GPGMail


[sqlalchemy] Integrity errors in foreign key with nullable=False in a large hierarchy

2014-01-09 Thread Paul Moore
The following is a stripped down example of my app, that does NOT show the 
problem:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref, sessionmaker
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy import create_engine

Base = declarative_base()

class Release(Base):
__tablename__ = 'releases'
id = Column(Integer, primary_key=True)
version = Column(String, nullable=False)
def __init__(self, version):
self.version = version
def __repr__(self):
return Release(version={}).format(self.version)

class URL(Base):
__tablename__ = 'urls'
id = Column(Integer, primary_key=True)
release_id = Column(Integer, ForeignKey('releases.id'), nullable=False)
url = Column(String, nullable=False)
release = relationship(Release,
cascade=all, delete-orphan,
single_parent=True,
backref=backref('urls', order_by=url))
def __repr__(self):
return URL(url={}).format(self.url)

def new_release(version, urls):
r = Release(version)
l = []
for url in urls:
u = URL()
u.url = url
l.append(u)
r.urls = l

return r

if __name__ == '__main__':
db = create_engine('sqlite://')
Base.metadata.create_all(db)
Session = sessionmaker(db)
s = Session()
s.merge(new_release('1.0', ['http://myapp.net/1.0']))
s.commit()

The real app is basically just a lot more complex (releases have 4 child 
lists like urls, my example adds multiple objects in each list. The app 
fails with an integrity error because a url has a null request_id. In 
actual fact, the hierarchy all gets built up properly in the end, but it 
appears that something is trying to save the children before all of the 
links are set up.

If I remove nullable=False from the foreign keys, it works fine.

I think one of the error tracebacks (sorry, I lost them in other output) 
mentioned autoflush - could the ORM be trying to flush bits of the 
hierarchy before it's complete? Is there a better fix than removing the 
nullable=False constraints?

Thanks for any help,
Paul

-- 
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.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] Integrity errors in foreign key with nullable=False in a large hierarchy

2014-01-09 Thread Michael Bayer

On Jan 9, 2014, at 4:02 PM, Paul Moore p.f.mo...@gmail.com wrote:

 The real app is basically just a lot more complex (releases have 4 child 
 lists like urls, my example adds multiple objects in each list. The app fails 
 with an integrity error because a url has a null request_id. In actual fact, 
 the hierarchy all gets built up properly in the end, but it appears that 
 something is trying to save the children before all of the links are set up.
 
 If I remove nullable=False from the foreign keys, it works fine.
 
 I think one of the error tracebacks (sorry, I lost them in other output) 
 mentioned autoflush - could the ORM be trying to flush bits of the hierarchy 
 before it's complete? Is there a better fix than removing the nullable=False 
 constraints?

absolutely, which is why the “no_autoflush” contextmanager exists:

http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html?highlight=no_autoflush#sqlalchemy.orm.session.Session.no_autoflush

the stack trace you’re getting will give you clues to where this context 
manager should go.  You’ll see the word “autoflush” in the stack trace, and 
from there you can trace up to see the specific operation in your app that is 
triggering it.



signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] Integrity errors in foreign key with nullable=False in a large hierarchy

2014-01-09 Thread Paul Moore
On Thursday, 9 January 2014 21:27:06 UTC, Michael Bayer wrote:

  I think one of the error tracebacks (sorry, I lost them in other output) 
 mentioned autoflush - could the ORM be trying to flush bits of the 
 hierarchy before it's complete? Is there a better fix than removing the 
 nullable=False constraints? 

 absolutely, which is why the “no_autoflush” contextmanager exists: 


 http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html?highlight=no_autoflush#sqlalchemy.orm.session.Session.no_autoflush
  

 the stack trace you’re getting will give you clues to where this context 
 manager should go.  You’ll see the word “autoflush” in the stack trace, and 
 from there you can trace up to see the specific operation in your app that 
 is triggering it. 

 
Thanks. That's exactly what I wanted :-)

Paul

-- 
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.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] SQLAlchemy not executing query

2014-01-09 Thread Sylvester Steele
Hi,
 
I am using SQLAlchemy version 0.7.6 with pyodbc to connect to MSSQL 2012. 
Currently I am using SQLAlchemy only for its connection pooling etc. So, at 
the moment I only use the engine.execute function to execute string 
queries. 
 
Weirdly, the following query seems to have no effect at all:
 
  SET NOCOUNT ON;
  SET ROWCOUNT 1
  WHILE 1 = 1
  BEGIN
 DELETE from MyTable where MyDate = '2030'
  IF @@rowcount  1
  BREAK;
  END
  SET ROWCOUNT 0;
  SET NOCOUNT OFF;
 
Running the above query using pyodbc directly, works. But with SQLAlchemy 
it has no effect. There is no error thrown, just a silent failure to 
execute. 
 
 
I enabled ODBC tracing and I found this:
 
python  -c imp 85bc-7d4c EXIT  SQLDriverConnectW  with return code 1 
(SQL_SUCCESS_WITH_INFO)
  HDBC0x0057B770
  HWND0x
  WCHAR * 0x07FEF8CB8F08 [  -3] **\ 0
  SWORD   -3 
  WCHAR * 0x07FEF8CB8F08 Invalid buffer length! [-3]
  SWORD   -3 
  SWORD * 0x
  UWORD0 SQL_DRIVER_NOPROMPT
 
However, the above was also present when I ran the query through pyodbc 
only. So, this probably indicates a more general problem with the set up, 
rather than something particular with SQLAlchemy.
 
Any idea what might be causing this?
 
Thanks

-- 
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.
For more options, visit https://groups.google.com/groups/opt_out.


[sqlalchemy] Why ORM objects in a session expire immediately after a failure in flush?

2014-01-09 Thread Weikai Xie
Hi, folks,

I observed that it seems all ORM objects  in a session will expire 
immediately if there is a failure in session.flush(). I was wondering 
what's the rationale behind this behavior.

Following is an artificial web application code to illustrate the idea:

def PUT():
   
  # session and engine are all created with default parameter

user = session.query(UserProfile).first()
   
# deliberately tries to insert a Login record which has the same 
primary key as an existing one such that the later session.flush() will fail
try:
   duplicated_login_record = Login(id=0, username=username:weikai)
   session.add(duplicated_login_record)
   session.flush()   
except IntegrityError:
session.rollback() 

print user.id   
...

By turning on logging, I noticed the print user.id line always result in 
a new SELECT being issued to database, which is an indicator that somehow 
user object got expired after the failure in session.flush().

For some other good reason which I don't want to elaborate here, we really 
don't want to have an extra SELECT going to DB in the processing of one 
HTTP request. Therefore, I was just wondering why is this behavior and 
whether it can be turned off. 

 


 

-- 
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.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] SQLAlchemy not executing query

2014-01-09 Thread Michael Bayer
The statement is likely being invoked but is in a transaction that isn’t 
getting committed (assuming you’re using commit() with pyodbc).   SQLAlchemy 
has an “autocommit” feature that by default looks for SQL strings that indicate 
a COMMIT should occur.  So in this case you should make sure there’s an 
explicit transaction or explicit autocommit.  In 0.7 you’re probably best off 
like this:

conn = engine.connect()
trans = conn.begin()
conn.execute(“your sql”)
trans.commit()

or use the “autocommit” option:

conn = engine.connect()
conn.execution_options(autocommit=True).execute(“your sql”)



On Jan 9, 2014, at 6:39 PM, Sylvester Steele sylvesterste...@gmail.com wrote:

 Hi,
  
 I am using SQLAlchemy version 0.7.6 with pyodbc to connect to MSSQL 2012.
 Currently I am using SQLAlchemy only for its connection pooling etc. So, at 
 the moment I only use the engine.execute function to execute string queries.
  
 Weirdly, the following query seems to have no effect at all:
  
   SET NOCOUNT ON;
   SET ROWCOUNT 1
   WHILE 1 = 1
   BEGIN
  DELETE from MyTable where MyDate = '2030'
   IF @@rowcount  1
   BREAK;
   END
   SET ROWCOUNT 0;
   SET NOCOUNT OFF;
  
 Running the above query using pyodbc directly, works. But with SQLAlchemy it 
 has no effect. There is no error thrown, just a silent failure to execute.
  
  
 I enabled ODBC tracing and I found this:
  
 python  -c imp 85bc-7d4c EXIT  SQLDriverConnectW  with return code 1 
 (SQL_SUCCESS_WITH_INFO)
   HDBC0x0057B770
   HWND0x
   WCHAR * 0x07FEF8CB8F08 [  -3] **\ 0
   SWORD   -3 
   WCHAR * 0x07FEF8CB8F08 Invalid buffer length! [-3]
   SWORD   -3 
   SWORD * 0x
   UWORD0 SQL_DRIVER_NOPROMPT
  
 However, the above was also present when I ran the query through pyodbc only. 
 So, this probably indicates a more general problem with the set up, rather 
 than something particular with SQLAlchemy.
  
 Any idea what might be causing this?
  
 Thanks
 
 -- 
 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.
 For more options, visit https://groups.google.com/groups/opt_out.



signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] Why ORM objects in a session expire immediately after a failure in flush?

2014-01-09 Thread Michael Bayer

On Jan 9, 2014, at 7:17 PM, Weikai Xie xiewei...@gmail.com wrote:

 Hi, folks,
 
 I observed that it seems all ORM objects  in a session will expire 
 immediately if there is a failure in session.flush(). I was wondering what's 
 the rationale behind this behavior.
 
 Following is an artificial web application code to illustrate the idea:
 
 def PUT():

   # session and engine are all created with default parameter
 
 user = session.query(UserProfile).first()

 # deliberately tries to insert a Login record which has the same 
 primary key as an existing one such that the later session.flush() will fail
 try:
duplicated_login_record = Login(id=0, username=username:weikai)
session.add(duplicated_login_record)
session.flush()   
 except IntegrityError:
 session.rollback() 
 
 print user.id   
 ...
 
 By turning on logging, I noticed the print user.id line always result in a 
 new SELECT being issued to database, which is an indicator that somehow user 
 object got expired after the failure in session.flush().
 
 For some other good reason which I don't want to elaborate here, we really 
 don't want to have an extra SELECT going to DB in the processing of one HTTP 
 request. Therefore, I was just wondering why is this behavior and whether it 
 can be turned off. 

The short answer is that this behavior can’t be disabled across the board, 
unless you are using SAVEPOINTs, which you probably should here.  The flush() 
process does a rollback() immediately on the inner transaction when an 
exception occurs, and once the transaction is rolled back all data is expired; 
as the objects are proxies for the state of the database, and the transaction 
has been rolled back, the state of the objects is invalid.

I do notice that you’re catching an IntegrityError.The typical pattern when 
writing code that wants to catch these and then continue is to run the 
individual set of questionable operations within a SAVEPOINT, that is a 
begin_nested()/commit() block.  Recent versions of SQLAlchemy have the behavior 
such that when a flush() exception rolls back the SAVEPOINT, objects that were 
not modified within the SAVEPOINT are not expired; only those objects that 
changed within the save point’s scope do.

There’s also an option called _enable_transaction_accounting which if set to 
False will disable *all* rollback/commit accounting, basically reverts to 
pre-0.5 behavior.  Using this flag, you’re giving up a lot of the Session’s 
functionality and as this mode is not really supported I’m not sure what other 
useful features you might be giving up.



 
  
 
 
  
 
 
 -- 
 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.
 For more options, visit https://groups.google.com/groups/opt_out.



signature.asc
Description: Message signed with OpenPGP using GPGMail