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

2014-01-10 Thread Laurence Rowe

On Thursday, 9 January 2014 09:41:40 UTC-8, Jeff Dairiki wrote:

 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. 

 
Yup, your analysis here looks correct to me:

- The SessionTransaction.close() does not call transaction.close() and in 
turn transaction.rollback() because the connection's autoclose  is True as 
``conn is not bind`` 
- 
https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_1/lib/sqlalchemy/orm/session.py#L431

https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_1/lib/sqlalchemy/orm/session.py#L297

When the connection is returned to the pool, it will rollback-on-return and 
that's throwing the exception as it is simply calling 
``pool._dialect.do_rollback(fairy)`` - 
https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_1/lib/sqlalchemy/pool.py#L408

When you call session.rollback() the engine's ``do_rollback_twophase()`` is 
being called which executes the appropirate XA ROLLBACK :xid 
- 
https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_1/lib/sqlalchemy/dialects/mysql/base.py#L2086

I think the ``pool._dialect.do_rollback`` and ``pool._dialect.do_commit`` 
calls in _finalize_fairy need to take account of the twophase nature of the 
connection.


I don't think zope.sqlalchemy should be involved here, as the pool 
configures how a connection should be closed with reset_on_return: 
http://docs.sqlalchemy.org/en/rel_0_9/core/pooling.html#sqlalchemy.pool.QueuePool.__init__.params.reset_on_return
 

Worth reporting as a SQLAlchemy bug, though fixing it cleanly looks rather 
tricky.

You might be able to rig something together with event listeners, but it 
looks tricky. For the pools reset event you won't have access to the xid 
and is_prepared of the TwoPhaseTransaction, so you'll need to store these 
on the connection during:

http://docs.sqlalchemy.org/en/rel_0_9/core/events.html#sqlalchemy.events.PoolEvents.reset
http://docs.sqlalchemy.org/en/rel_0_9/core/events.html#sqlalchemy.events.ConnectionEvents.begin_twophase
http://docs.sqlalchemy.org/en/rel_0_9/core/events.html#sqlalchemy.events.ConnectionEvents.prepare_twophase

I think this should do it (untested):

from sqlalchemy import event

@event.listens_for(SomeEngine, 'begin_twophase')
def receive_begin_twophase(conn, xid):
conn._note_xid_prepared = (xid, False)


@event.listens_for(SomeEngine, 'prepare_twophase')
def receive_prepare_twophase(conn, xid):
conn._note_xid_prepared = (xid, True)


@event.listens_for(SomeEngineOrPool, 'reset')
def receive_reset(dbapi_con, con_record):
conn = con_record.connection
if not hasattr(conn, '_note_xid_prepared'):

Re: [sqlalchemy] Multiple inheritance issue

2014-01-10 Thread Enrico Bottani
Thank you very much MichaeI was in fact thinking that it was possible to 
not found support for that feature. But as you said, the compiler didn't 
shout at me and the application was running fine so I was thinking that I 
was doing things right.
I'll go for the JOIN.


Best,

Enrico

On Thursday, January 9, 2014 8:15:14 PM UTC+1, Michael Bayer wrote:


 On Jan 9, 2014, at 11:32 AM, Enrico Bottani bei...@mac.com javascript: 
 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 
 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?


 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+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.comjavascript:
 .
 Visit this group at http://groups.google.com/group/sqlalchemy.
 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] Polymorphic joined-table inheritance

2014-01-10 Thread david . ceresuela
Hello all,

I'm trying to use SQLAlchemy inheritance in a (company's) project and I 
cannot seem to make it work.

First, the versions:
- Ubuntu: 12.10
- Python: 2.7.3
- SQLAlchemy: 0.9.1
- PostgreSQL: 9.1
- sqlite: 3.7.13
- Pyramid: 1.4.2
All of the problems happen in both PostgreSQL and sqlite.

I have a ClientVip class that inherits from Client. This is the trimmed 
code:

##
class Client(Base):
__tablename__ = 'client'
id = Column(Integer, primary_key=True)
ctype = Column(String(16), nullable=False)
webaddid = Column(Integer, ForeignKey('web.id'), nullable=False)
parentid = Column(Integer, ForeignKey('client.id'), nullable=True)
refinternal = Column(Integer, unique=True, nullable=False)
...
notestx = Column(String(256), nullable=True)
notesclient = Column(String(256), nullable=True)

__mapper_args__ = {
'polymorphic_identity':'basic',
'polymorphic_on': ctype
}

def __init__(self, webaddid=None, parentid=None, refinternal=None,
...
notestx=None, notesclient=None):
# self.ctype = basic   ### This is actually commented, but might 
be important
self.webaddid = webaddid
self.parentid = parentid
self.refinternal = refinternal
...
self.notesclient = notesclient


class ClientVip(Client):
__tablename__ = 'clientvip'
id = Column(Integer, ForeignKey('client.id'), primary_key=True)
legalname = Column(String(128), nullable=True)
commercialname = Column(String(64), nullable=True)
...
isclienttop = Column(Boolean, nullable=False)
numlisttop = Column(Integer, nullable=True)

# Fill the column 'ctype' with the value 'vip'
__mapper_args__ = {
'polymorphic_identity':'vip',
}

def __init__(self, clientid=None, legalname=None, commercialname=None,
 ...
 isclienttop=False, numlisttop=None, **kwargs):

# First initialize the basic client
super(ClientVip, self).__init__(**kwargs)

# And then the VIP client
# self.ctype = vip### This is actually commented, but might 
be important
self.clientid = clientid
self.legalname = legalname
self.commercialname = commercialname
...
self.isclienttop = isclienttop
self.numlisttop = numlisttop
##

I have checked the code in
 - 
http://docs.sqlalchemy.org/en/rel_0_9/orm/examples.html?highlight=inheritance#module-examples.inheritance
 - 
http://docs.sqlalchemy.org/en/rel_0_9/_modules/examples/inheritance/joined.html
and I can't find anything different, but maybe are my eyes.


Problem: Querying client and clientvip
---

With this code I try to query all the clients [ clients = 
DBSession.query(Client) ]
and this is where the problems start, because the query it is issuing is:

##
SELECT client.id AS client_id, client.ctype AS client_ctype, 
client.refinternal AS client_refinternal, 
...
client.notestx AS client_notestx, client.notesclient AS client_notesclient 
FROM client 
WHERE client.ctype IN (NULL)
##

Why is there a where clause at all? Should not the query finish with the 
FROM client line?
And besides, why does it think that ctype must be NULL (instead of basic 
or vip, for instance)?


If a force to query with a filter [ clients = 
DBSession.query(Client).filter(Client.ctype == basic) ]
this is the query I get:

##
SELECT client.id AS client_id, client.ctype AS client_ctype, 
client.refinternal AS client_refinternal,
...
client.notestx AS client_notestx, client.notesclient AS client_notesclient 
FROM client 
WHERE client.ctype = %(ctype_1)s AND client.ctype IN (NULL)
##

which also looks for NULL values in the where clause.


And what happens if I query the ClientVip?
Well, there are no where clauses, so we are good:

##
SELECT clientvip.id AS clientvip_id, client.id AS client_id, client.ctype 
AS client_ctype, client.refinternal AS client_refinternal,
...
clientvip.isclienttop AS clientvip_isclienttop, clientvip.numlisttop AS 
clientvip_numlisttop 
FROM client JOIN clientvip ON client.id = clientvip.id
##


Appendix: Inserting client
-

You might have seen that in the __init__ methods I have commented out the  
self.ctype = 'basic' 
When this line is commented out (as it should) and I try to insert a 
Client, I get the following error:

##
IntegrityError: (IntegrityError) null value in column ctype violates 
not-null constraint
##

which leads me to think that the polymorphism I am trying to get is not 
working properly, becasue
I shouldn't need to force a value on the ctype column.


A plea for help
-

I have been looking at this code for quite some time and I can't figure out 
what I am missing.
If any of you have any idea of what I could be possibly doing wrong, or any 
ideas that I could
try, I will be very very happy to hear them, because I have run out of 
ideas 

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

2014-01-10 Thread Claudio Freire
On Thu, Jan 9, 2014 at 9:59 PM, Michael Bayer mike...@zzzcomputing.com wrote:
 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.

How recent does recent mean there? (just curious)

-- 
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] Is there a good ORM tutorial? And advice on parent/child management

2014-01-10 Thread Paul Moore
I'm developing an application using the ORM, and I am getting into all 
sorts of trouble with what I think should be a pretty simple data model. 
I've tried following the ORM tutorial from the docs, but it seems to get me 
confused every time I try. So I'm looking for something else that maybe 
takes a different approach. Or maybe someone can point out what's wrong for 
me in the following - but even then, pointers to other tutorial material 
would be useful, as I don't really want to end up pestering the list every 
time I hit an issue :-)

My data model is fairly straightforward. I have a Package class, with a 
name. I then have a Release class - each Release is associated with a 
single package, and has a unique version. Releases have a few children - 
Classifiers, Dependencies, and URLs. All of these are multi-valued with no 
natural key (at least, not one worth worrying about). There is some extra 
data associated with Releases and URLs, but that's not too important. 
(People may recognise this as the PyPI data model). This is a pretty 
trivial parent/child one-to-many hierarchy, and I didn't expect it to be 
hard to model.

The obvious (to me!) model is basically (trimmed down a bit):

class Package(Base):
__tablename__ = 'packages'
# Use a synthetic key, as package names can change
id = Column(Integer, primary_key=True)
name = Column(String, unique=True, nullable=False)
releases = relationship(Release, backref=package,
cascade=all, delete-orphan)

class Release(Base):
__tablename__ = 'releases'
id = Column(Integer, primary_key=True)
package_id = Column(Integer, ForeignKey('packages.id'), nullable=False)
version = Column(String, nullable=False) # Unique within package
classifiers = relationship(Classifier, backref=release,
cascade=all, delete-orphan)

class Classifier(Base):
__tablename__ = 'classifiers'
id = Column(Integer, primary_key=True)
release_id = Column(Integer, ForeignKey('releases.id'), nullable=False)
classifier = Column(String, nullable=False)

So far, so good. But if I want to create a new Release, things get messy. 
This is my basic function:

def new_release(package, version, data):
r = Release(version)
r.package = Package(package)
# Populate the data in r, and create child items
return r

It's that package reference that messes me up. If the release is for a new 
package, then when I merge the release into the session, the package is 
created. But if it's for an existing package, a new package is created 
(which gives a constraint error if the package name is unique, and 
duplicates if it's not) rather than the session recognising that it's an 
existing package and linking the release to it.

If I was working at the SQL core level, I'd expect to have to query for the 
package and create it if it wasn't there. But I'm not sure I can do that 
with a session, as things get cached in memory by the unit of work stuff, 
and I don't know if a query for the release could miss a package that's 
pending insertion, or if the query could cause auto-flushing which might 
cause other issues (either with performance or integrity). Because the 
session is managing the in-memory caching and the transaction management 
by magic, I don't want to interfere with its mechanisms any more than I 
have to. If I have to keep track of what's gone to the database, and query 
for existing instances and manage the transactions, I probably should just 
use the SQL layer directly (I have a lot of experiences with databases, but 
very little with ORMs, so pure DB code isn't too scary for me, but on the 
other hand I don't know what benefits the ORM should be giving me that I'm 
not seeing).

Is this an application that doesn't actually benefit from the ORM? Or am I 
using it wrongly, and my problems come from misunderstanding the way it 
should be used? As I say, I've a lot of database experience but very little 
with ORMs, so maybe I have an unbalanced view of how much data management 
the ORM should be able to handle for me.

The particular problem here is what's affecting me right now - but I'd be 
even more interested in a good ORM for experienced SQL developers 
tutorial that tells me how the ORM differs from the core level (and where 
its benefits lie).

Thanks,
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] Anybody have twophase/zope.sqlalchemy/MySQL working?

2014-01-10 Thread Michael Bayer

On Jan 10, 2014, at 3:32 AM, Laurence Rowe laurencer...@gmail.com wrote:

 
 On Thursday, 9 January 2014 09:41:40 UTC-8, Jeff Dairiki wrote:
 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. 
  
 Yup, your analysis here looks correct to me:
 
 - The SessionTransaction.close() does not call transaction.close() and in 
 turn transaction.rollback() because the connection's autoclose  is True as 
 ``conn is not bind`` - 
 https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_1/lib/sqlalchemy/orm/session.py#L431
 
 https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_1/lib/sqlalchemy/orm/session.py#L297
 
 When the connection is returned to the pool, it will rollback-on-return and 
 that's throwing the exception as it is simply calling 
 ``pool._dialect.do_rollback(fairy)`` - 
 https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_1/lib/sqlalchemy/pool.py#L408
 
 When you call session.rollback() the engine's ``do_rollback_twophase()`` is 
 being called which executes the appropirate XA ROLLBACK :xid - 
 https://github.com/zzzeek/sqlalchemy/blob/rel_0_9_1/lib/sqlalchemy/dialects/mysql/base.py#L2086
 
 I think the ``pool._dialect.do_rollback`` and ``pool._dialect.do_commit`` 
 calls in _finalize_fairy need to take account of the twophase nature of the 
 connection.

maybe.   I was thinking, is the Session really doing the right thing here by 
not getting involved, but I think yeah that still might be appropriate.  so 
we’d need to carry along some extra information about the transaction with the 
connection so that do_rollback() and do_commit() can pick up on that.

or maybe session.close() needs to do some bookkeeping with the 
SessionTransaction.   not sure.




signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] Is there a good ORM tutorial? And advice on parent/child management

2014-01-10 Thread Kevin Horn
It sounds to me like the problem you're having has to do with how you are
getting the reference to the package, which isn't shown in your example.
 How are you getting it?

The session doesn't do anything by magic, even if it seems that way
sometimes.  It just manages things behind the scenes.

If you want a new Package, create a new Package object.  If you want an
exisiting package, query for it.  Just like you would in bare SQL code.

If you don't know which you need, try searching and create it if it isn't
found.  I usually do something like:

try:
pkg = session.query(Package).filter(condition-goes-here)
except sa.orm.exc.NotFound:
pkg = Package()
# populate attributes and add to session

This is off the top of my head and from memory, so beware of possible
(probable) errors, but hopefully you get the idea.

Unfortunately (fortunately?) the SQLAlchemy docs are good enough that there
isn't a huge impetus for people outside the project to write tutorials,
blog posts, etc.  I'd like to see more of that kind of thing as well, but
everyone has limited time, I guess.

Good luck!



On Fri, Jan 10, 2014 at 7:44 AM, Paul Moore p.f.mo...@gmail.com wrote:

 I'm developing an application using the ORM, and I am getting into all
 sorts of trouble with what I think should be a pretty simple data model.
 I've tried following the ORM tutorial from the docs, but it seems to get me
 confused every time I try. So I'm looking for something else that maybe
 takes a different approach. Or maybe someone can point out what's wrong for
 me in the following - but even then, pointers to other tutorial material
 would be useful, as I don't really want to end up pestering the list every
 time I hit an issue :-)

 My data model is fairly straightforward. I have a Package class, with a
 name. I then have a Release class - each Release is associated with a
 single package, and has a unique version. Releases have a few children -
 Classifiers, Dependencies, and URLs. All of these are multi-valued with no
 natural key (at least, not one worth worrying about). There is some extra
 data associated with Releases and URLs, but that's not too important.
 (People may recognise this as the PyPI data model). This is a pretty
 trivial parent/child one-to-many hierarchy, and I didn't expect it to be
 hard to model.

 The obvious (to me!) model is basically (trimmed down a bit):

 class Package(Base):
 __tablename__ = 'packages'
 # Use a synthetic key, as package names can change
 id = Column(Integer, primary_key=True)
 name = Column(String, unique=True, nullable=False)
 releases = relationship(Release, backref=package,
 cascade=all, delete-orphan)

 class Release(Base):
 __tablename__ = 'releases'
 id = Column(Integer, primary_key=True)
 package_id = Column(Integer, ForeignKey('packages.id'),
 nullable=False)
 version = Column(String, nullable=False) # Unique within package
 classifiers = relationship(Classifier, backref=release,
 cascade=all, delete-orphan)

 class Classifier(Base):
 __tablename__ = 'classifiers'
 id = Column(Integer, primary_key=True)
 release_id = Column(Integer, ForeignKey('releases.id'),
 nullable=False)
 classifier = Column(String, nullable=False)

 So far, so good. But if I want to create a new Release, things get messy.
 This is my basic function:

 def new_release(package, version, data):
 r = Release(version)
 r.package = Package(package)
 # Populate the data in r, and create child items
 return r

 It's that package reference that messes me up. If the release is for a new
 package, then when I merge the release into the session, the package is
 created. But if it's for an existing package, a new package is created
 (which gives a constraint error if the package name is unique, and
 duplicates if it's not) rather than the session recognising that it's an
 existing package and linking the release to it.

 If I was working at the SQL core level, I'd expect to have to query for
 the package and create it if it wasn't there. But I'm not sure I can do
 that with a session, as things get cached in memory by the unit of work
 stuff, and I don't know if a query for the release could miss a package
 that's pending insertion, or if the query could cause auto-flushing which
 might cause other issues (either with performance or integrity). Because
 the session is managing the in-memory caching and the transaction
 management by magic, I don't want to interfere with its mechanisms any
 more than I have to. If I have to keep track of what's gone to the
 database, and query for existing instances and manage the transactions, I
 probably should just use the SQL layer directly (I have a lot of
 experiences with databases, but very little with ORMs, so pure DB code
 isn't too scary for me, but on the other hand I don't know what benefits
 the ORM should be giving me that I'm not seeing).

 Is this an application that doesn't 

Re: [sqlalchemy] Polymorphic joined-table inheritance

2014-01-10 Thread Kevin Horn
I'm not really sure, but you probably need to be calling super() somewhere
in Client.__init__, which you don't seem to be doing.

The main difference between your code and what I would usually do is that I
almost never override __init__ in my models.  I expect some of the setup
for inheritance happens in DeclarativeBase (Base in your example) and that
isn't getting called, so never happens.

Try removing your __init__ methods as an easy troubleshooting step, and if
that works you know your problem is there.


On Fri, Jan 10, 2014 at 6:08 AM, david.ceresu...@gmail.com wrote:

 Hello all,

 I'm trying to use SQLAlchemy inheritance in a (company's) project and I
 cannot seem to make it work.

 First, the versions:
 - Ubuntu: 12.10
 - Python: 2.7.3
 - SQLAlchemy: 0.9.1
 - PostgreSQL: 9.1
 - sqlite: 3.7.13
 - Pyramid: 1.4.2
 All of the problems happen in both PostgreSQL and sqlite.

 I have a ClientVip class that inherits from Client. This is the trimmed
 code:

 ##
 class Client(Base):
 __tablename__ = 'client'
 id = Column(Integer, primary_key=True)
 ctype = Column(String(16), nullable=False)
 webaddid = Column(Integer, ForeignKey('web.id'), nullable=False)
 parentid = Column(Integer, ForeignKey('client.id'), nullable=True)
 refinternal = Column(Integer, unique=True, nullable=False)
 ...
 notestx = Column(String(256), nullable=True)
 notesclient = Column(String(256), nullable=True)

 __mapper_args__ = {
 'polymorphic_identity':'basic',
 'polymorphic_on': ctype
 }

 def __init__(self, webaddid=None, parentid=None, refinternal=None,
 ...
 notestx=None, notesclient=None):
 # self.ctype = basic   ### This is actually commented, but might
 be important
 self.webaddid = webaddid
 self.parentid = parentid
 self.refinternal = refinternal
 ...
 self.notesclient = notesclient


 class ClientVip(Client):
 __tablename__ = 'clientvip'
 id = Column(Integer, ForeignKey('client.id'), primary_key=True)
 legalname = Column(String(128), nullable=True)
 commercialname = Column(String(64), nullable=True)
 ...
 isclienttop = Column(Boolean, nullable=False)
 numlisttop = Column(Integer, nullable=True)

 # Fill the column 'ctype' with the value 'vip'
 __mapper_args__ = {
 'polymorphic_identity':'vip',
 }

 def __init__(self, clientid=None, legalname=None, commercialname=None,
  ...
  isclienttop=False, numlisttop=None, **kwargs):

 # First initialize the basic client
 super(ClientVip, self).__init__(**kwargs)

 # And then the VIP client
 # self.ctype = vip### This is actually commented, but might
 be important
 self.clientid = clientid
 self.legalname = legalname
 self.commercialname = commercialname
 ...
 self.isclienttop = isclienttop
 self.numlisttop = numlisttop
 ##

 I have checked the code in
  -
 http://docs.sqlalchemy.org/en/rel_0_9/orm/examples.html?highlight=inheritance#module-examples.inheritance
  -
 http://docs.sqlalchemy.org/en/rel_0_9/_modules/examples/inheritance/joined.html
 and I can't find anything different, but maybe are my eyes.


 Problem: Querying client and clientvip
 ---

 With this code I try to query all the clients [ clients =
 DBSession.query(Client) ]
 and this is where the problems start, because the query it is issuing is:

 ##
 SELECT client.id AS client_id, client.ctype AS client_ctype,
 client.refinternal AS client_refinternal,
 ...
 client.notestx AS client_notestx, client.notesclient AS client_notesclient
 FROM client
 WHERE client.ctype IN (NULL)
 ##

 Why is there a where clause at all? Should not the query finish with the
 FROM client line?
 And besides, why does it think that ctype must be NULL (instead of basic
 or vip, for instance)?


 If a force to query with a filter [ clients =
 DBSession.query(Client).filter(Client.ctype == basic) ]
 this is the query I get:

 ##
 SELECT client.id AS client_id, client.ctype AS client_ctype,
 client.refinternal AS client_refinternal,
 ...
 client.notestx AS client_notestx, client.notesclient AS client_notesclient
 FROM client
 WHERE client.ctype = %(ctype_1)s AND client.ctype IN (NULL)
 ##

 which also looks for NULL values in the where clause.


 And what happens if I query the ClientVip?
 Well, there are no where clauses, so we are good:

 ##
 SELECT clientvip.id AS clientvip_id, client.id AS client_id, client.ctype
 AS client_ctype, client.refinternal AS client_refinternal,
 ...
 clientvip.isclienttop AS clientvip_isclienttop, clientvip.numlisttop AS
 clientvip_numlisttop
 FROM client JOIN clientvip ON client.id = clientvip.id
 ##


 Appendix: Inserting client
 -

 You might have seen that in the __init__ methods I have commented out the
  self.ctype = 

Re: [sqlalchemy] Is there a good ORM tutorial? And advice on parent/child management

2014-01-10 Thread Paul Moore
On Friday, 10 January 2014 16:27:12 UTC, Kevin H wrote:

 It sounds to me like the problem you're having has to do with how you are 
 getting the reference to the package, which isn't shown in your example. 
  How are you getting it?


The new_release() function is what I do - I create a new Package object. I 
was under the impression that when I did a session.merge() that would match 
up existing objects. I'm probably being naive in that, though...
 

 The session doesn't do anything by magic, even if it seems that way 
 sometimes.  It just manages things behind the scenes.


Hmm - managing things behind the scenes is what I was meaning by magic. 
The problem is that I can't find any clear reference about what is, and 
what is not, managed behind the scenes. As I said, it's more about my 
understanding (and hence about me knowing what code I need to write) than 
about SQLAlchemy doing anything wrong.
 

 If you want a new Package, create a new Package object.  If you want an 
 exisiting package, query for it.  Just like you would in bare SQL code.

 If you don't know which you need, try searching and create it if it isn't 
 found.  I usually do something like:

 try:
 pkg = session.query(Package).filter(condition-goes-here)
 except sa.orm.exc.NotFound:
 pkg = Package()
 # populate attributes and add to session


OK. That's essentially what I was hoping to avoid. Largely because of that 
query - I may not yet have committed the package to the database.

For a more extended example, suppose I do the following:

p = Package(pip)
session.merge(p) # I could do session.add here, but I'm not 100% clear 
why just doing merge isn't better in case I'm not sure if pip is already 
present

Somewhere a little later, in other code where I haven't committed yet, but 
I don't have a reference to p available:

r = Release(1.5)
r.package = Package(pip)

Can I query for pip here? There's been no commit yet, and there may not 
even have been a flush (I've had problems with null foreign keys so I've 
had to force autoflush off in a few places). Essentially, will a query 
locate an object that's in session.new but which hasn't been flushed to the 
database yet?

This is the crux of my issue. I really don't understand why I'm getting 
null foreign keys on autoflush, but switching autoflush off seems to fix 
it. But maybe that's what's giving me these issues, so maybe I need to turn 
autoflush back on. But then what do I do about my noll FKs?

Unfortunately (fortunately?) the SQLAlchemy docs are good enough that there 
 isn't a huge impetus for people outside the project to write tutorials, 
 blog posts, etc.  I'd like to see more of that kind of thing as well, but 
 everyone has limited time, I guess.


Without wishing to seem critical, I find the ORM docs pretty difficult to 
follow. They seem to jump around between schema design (DDL) and usage 
(select and DML) in a pretty haphazard fashion, and the information about 
transactional control and session management seems to be spread around the 
various sections. That's basically just my perspective, and may reflect my 
experience, but it is frustrating. Agreed entirely about people having 
limited time, and the docs are certainly far better than a lot that's 
around.

Maybe I'll just have to have a thorough read of the docs before I carry on 
coding. Feels like I'm making more problems than I'm solving right now. Or 
maybe stick to what I know and drop back to the SQL core stuff.

Thanks for the 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] Is there a good ORM tutorial? And advice on parent/child management

2014-01-10 Thread Kevin Horn
On Fri, Jan 10, 2014 at 10:55 AM, Paul Moore p.f.mo...@gmail.com wrote:

 On Friday, 10 January 2014 16:27:12 UTC, Kevin H wrote:

 It sounds to me like the problem you're having has to do with how you are
 getting the reference to the package, which isn't shown in your example.
  How are you getting it?


 The new_release() function is what I do - I create a new Package object. I
 was under the impression that when I did a session.merge() that would match
 up existing objects. I'm probably being naive in that, though...


I don't think merge() does what you think it does. (Beware...I don't ever
really use it, so I am not an expert in it's use).  My understanding is
that merge takes an input instance, looks it up or creates a new instance
based on the primary key of the input instance, and copies data from the
input instance to the lookedup/created one, and then returns that.  If your
input instance doesn't have a primary key...well, that doesn't seem to make
sense and I really don't know what happens.  maybe this is the root of your
problem?

Personally, I stay away from merge() if at all possible, since it can be
way more complex than I want to deal with.

I would recommend trying to do things in the simplest way you can get away
with, and see whether that can help you increase your understanding.  Try
using add() and see if that helps you grok a bit more.


  The session doesn't do anything by magic, even if it seems that way
 sometimes.  It just manages things behind the scenes.

 Hmm - managing things behind the scenes is what I was meaning by magic.
 The problem is that I can't find any clear reference about what is, and
 what is not, managed behind the scenes. As I said, it's more about my
 understanding (and hence about me knowing what code I need to write) than
 about SQLAlchemy doing anything wrong.


 If you want a new Package, create a new Package object.  If you want an
 exisiting package, query for it.  Just like you would in bare SQL code.

 If you don't know which you need, try searching and create it if it isn't
 found.  I usually do something like:

 try:
 pkg = session.query(Package).filter(condition-goes-here)
 except sa.orm.exc.NotFound:
 pkg = Package()
 # populate attributes and add to session


 OK. That's essentially what I was hoping to avoid. Largely because of that
 query - I may not yet have committed the package to the database.


I don't think it has to be committed yet, it just has to exist in the
session.  See below.


 For a more extended example, suppose I do the following:

 p = Package(pip)
 session.merge(p) # I could do session.add here, but I'm not 100% clear
 why just doing merge isn't better in case I'm not sure if pip is already
 present


Because p doesn't have a primary key yet?  I'm kind of guessing...but I
really think you need a pkey on the input object to merge().


 Somewhere a little later, in other code where I haven't committed yet, but
 I don't have a reference to p available:

 r = Release(1.5)
 r.package = Package(pip)

 Can I query for pip here? There's been no commit yet, and there may not
 even have been a flush (I've had problems with null foreign keys so I've
 had to force autoflush off in a few places). Essentially, will a query
 locate an object that's in session.new but which hasn't been flushed to the
 database yet?


If you use session.add() then yes, you can query for pip there.  The ORM
will find it.  On Postgres, at least, it seems that when you add it to the
session, it grabs a value from the sequence used for the primary key, but
doesn't yet add the actual row (in this case...other cases might be more
complex) for the package.  So the session knows what the primary key will
be once you commit the package, and can use that to find the package.

At least that's how it looks like it works, and how I think about it.  I
don't claim to know what it actually does.


 This is the crux of my issue. I really don't understand why I'm getting
 null foreign keys on autoflush, but switching autoflush off seems to fix
 it. But maybe that's what's giving me these issues, so maybe I need to turn
 autoflush back on. But then what do I do about my noll FKs?


I'm not sure what to say about this.  Probably we're hitting the limits of
my understanding here.


 Unfortunately (fortunately?) the SQLAlchemy docs are good enough that
 there isn't a huge impetus for people outside the project to write
 tutorials, blog posts, etc.  I'd like to see more of that kind of thing as
 well, but everyone has limited time, I guess.


 Without wishing to seem critical, I find the ORM docs pretty difficult to
 follow. They seem to jump around between schema design (DDL) and usage
 (select and DML) in a pretty haphazard fashion, and the information about
 transactional control and session management seems to be spread around the
 various sections. That's basically just my perspective, and may reflect my
 experience, but it is frustrating. Agreed entirely about 

Re: [sqlalchemy] Polymorphic joined-table inheritance

2014-01-10 Thread Michael Bayer
On Jan 10, 2014, at 7:08 AM, david.ceresu...@gmail.com wrote:Problem: Querying client and clientvip---With this code I try to query all the clients [ clients = DBSession.query(Client) ]and this is where the problems start, because the query it is issuing is:##SELECT client.id AS client_id, client.ctype AS client_ctype, client.refinternal AS client_refinternal, ...client.notestx AS client_notestx, client.notesclient AS client_notesclient FROM client WHERE client.ctype IN (NULL)##Why is there a where clause at all? Should not the query finish with the "FROM client" line?And besides, why does it think that ctype must be NULL (instead of "basic" or "vip", for instance)?that’s a very strange output, the IN is applied to single-table inheritance mappings in order to limit the types of returned classes to those which are queried. The mapping you’ve illustrated should not have this issue and in fact as Client is at the base, there shouldn’t be any IN at all.I’ve copied your mappings verbatim to a test case, a query against Client produces this:SELECT client.id AS client_id, client.ctype AS client_ctype, client.parentid AS client_parentid, client.refinternal AS client_refinternal, client.notestx AS client_notestx, client.notesclient AS client_notesclientFROM clientso more specifics would be needed to determine why this obviously erroneous output is being produced. The constructor of Client is not involved with this issue as a Query only works against the class, not an instance.Appendix: Inserting client-You might have seen that in the __init__ methods I have commented out the " self.ctype = 'basic' "When this line is commented out (as it should) and I try to insert a Client, I get the following error:##IntegrityError: (IntegrityError) null value in column "ctype" violates not-null constraint##which leads me to think that the polymorphism I am trying to get is not working properly, becasueI shouldn't need to force a value on the "ctype" column.you absolutely don’t need to worry about “ctype”, nor do you need to worry about calling super(). the polymorphic identity is set on the instance using an on-init event.  I can again use your mappings as is, then run code like this:c1 = Client(refinternal=5)sess.add(c1)sess.commit()and the output:INSERT INTO client (ctype, parentid, refinternal, notestx, notesclient) VALUES (?, ?, ?, ?, ?)2014-01-10 12:39:14,949 INFO sqlalchemy.engine.base.Engine ('basic', None, 5, None, None)2014-01-10 12:39:14,949 INFO sqlalchemy.engine.base.Engine COMMITso no problems there either.Both issues seem to focus around the polymorphic_identity configuration of your setup but the code examples you’ve sent don’t indicate any such issue.If you can attach a simple “test.py” similar to the one attached which reproduces the issue, we can fix your problem immediately.from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Client(Base):
__tablename__ = 'client'
id = Column(Integer, primary_key=True)
ctype = Column(String(16), nullable=False)
#webaddid = Column(Integer, ForeignKey('web.id'), nullable=False)
parentid = Column(Integer, ForeignKey('client.id'), nullable=True)
refinternal = Column(Integer, unique=True, nullable=False)
notestx = Column(String(256), nullable=True)
notesclient = Column(String(256), nullable=True)

__mapper_args__ = {
'polymorphic_identity':'basic',
'polymorphic_on': ctype
}

def __init__(self, webaddid=None, parentid=None, refinternal=None,
notestx=None, notesclient=None):
self.webaddid = webaddid
self.parentid = parentid
self.refinternal = refinternal
self.notesclient = notesclient


class ClientVip(Client):
__tablename__ = 'clientvip'
id = Column(Integer, ForeignKey('client.id'), primary_key=True)
legalname = Column(String(128), nullable=True)
commercialname = Column(String(64), nullable=True)
isclienttop = Column(Boolean, nullable=False)
numlisttop = Column(Integer, nullable=True)

# Fill the column 'ctype' with the value 'vip'
__mapper_args__ = {
'polymorphic_identity':'vip',
}

def __init__(self, clientid=None, legalname=None, commercialname=None,
 isclienttop=False, numlisttop=None, **kwargs):

# First initialize the basic client
super(ClientVip, self).__init__(**kwargs)

self.clientid = clientid
self.legalname = legalname
self.commercialname = commercialname
self.isclienttop = isclienttop
self.numlisttop = numlisttop


e = create_engine(sqlite://, echo=True)
Base.metadata.create_all(e)
sess = Session(e)


c1 = Client(refinternal=5)
c2 = ClientVip(refinternal=6)

sess.add(c1)
sess.add(c2)
sess.commit()


clients = set(sess.query(Client).all())

assert clients == set([c1, c2])

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

2014-01-10 Thread Michael Bayer
changelog in 0.8.0b1:

http://docs.sqlalchemy.org/en/rel_0_9/changelog/changelog_08.html#change-1df6e3552ee895cd48952f95c0f0730a

ticket:

http://www.sqlalchemy.org/trac/ticket/2452

I wonder if offering that the automatic rollback() on flush() might be 
optionally disabled (which means, a corrupted flush is in danger of being 
committed if the user is not careful) would be a compromise for this behavior 
in the bigger sense.




On Jan 10, 2014, at 8:41 AM, Claudio Freire klaussfre...@gmail.com wrote:

 On Thu, Jan 9, 2014 at 9:59 PM, Michael Bayer mike...@zzzcomputing.com 
 wrote:
 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.
 
 How recent does recent mean there? (just curious)
 
 -- 
 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] Is there a good ORM tutorial? And advice on parent/child management

2014-01-10 Thread Michael Bayer

On Jan 10, 2014, at 8:44 AM, Paul Moore p.f.mo...@gmail.com wrote:

 
 So far, so good. But if I want to create a new Release, things get messy. 
 This is my basic function:
 
 def new_release(package, version, data):
 r = Release(version)
 r.package = Package(package)
 # Populate the data in r, and create child items
 return r
 
 It's that package reference that messes me up. If the release is for a new 
 package, then when I merge the release into the session, the package is 
 created. But if it's for an existing package, a new package is created (which 
 gives a constraint error if the package name is unique, and duplicates if 
 it's not) rather than the session recognising that it's an existing package 
 and linking the release to it.
 
 If I was working at the SQL core level, I'd expect to have to query for the 
 package and create it if it wasn't there. But I'm not sure I can do that with 
 a session, as things get cached in memory by the unit of work stuff, and I 
 don't know if a query for the release could miss a package that's pending 
 insertion, or if the query could cause auto-flushing which might cause other 
 issues (either with performance or integrity). Because the session is 
 managing the in-memory caching and the transaction management by magic, I 
 don't want to interfere with its mechanisms any more than I have to. If I 
 have to keep track of what's gone to the database, and query for existing 
 instances and manage the transactions, I probably should just use the SQL 
 layer directly (I have a lot of experiences with databases, but very little 
 with ORMs, so pure DB code isn't too scary for me, but on the other hand I 
 don't know what benefits the ORM should be giving me that I'm not seeing).

there’s various patterns for dealing with the very common issue of “create 
unique object if not exists, else use the current one”.  One that I frequently 
point to is the unique object recipe:

http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject

uniqueobject is a generalization.   You can of course just run the specific 
query yourself.  this is not in any way interfering with the ORM mechanisms - 
the unit of work is pretty much a simple identity dictionary in this sense, 
either a key exists for a given identity or it doesn’t (but keep in mind, 
“identity” to the unit of work means, “primary key identity”.  Not any of the 
other columns that are just part of unique constraints).

As mentioned elsewhere, Session.merge() kind of does this as well, but merge() 
only does so with the primary key of the instance, not for arbitrary fields, 
and I would agree that merge() is often more trouble than it’s worth - its 
complexity is that it can cascade the merge operation along relationships, not 
often needed for simple cases.




signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] SQLAlchemy not executing query

2014-01-10 Thread Sylvester Steele
Thank you that worked.


On Thu, Jan 9, 2014 at 7:47 PM, Michael Bayer mike...@zzzcomputing.comwrote:

 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.




-- 
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] Is there a good ORM tutorial? And advice on parent/child management

2014-01-10 Thread Paul Moore
On Friday, 10 January 2014 17:52:45 UTC, Michael Bayer wrote:

 there’s various patterns for dealing with the very common issue of “create 
 unique object if not exists, else use the current one”.  One that I 
 frequently point to is the unique object recipe: 


OK, so looking at that seems to imply that

pkg = Package(name=pip)
session.add(pkg)
is_it_there = session.query(Package).filter(Package.name == 'pip').first()
assert is_it_there is pkg

will fail the assertion (unless there is a flush). Otherwise, I don't see 
why the unique cache is needed in the recipe you reference.

I think I'm still missing something here...
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] Custom logic for query execution

2014-01-10 Thread Sylvester Steele
Hi,
Currently I am using the sqlalchemy engine to execute string queries only. 
I do plan on using sqlalchemy more extensively (including ORM) in the near 
future. 
I need to add retry logic on every query, in case of some database failures 
(less than ideal, but the server is a bit flaky). 

Questions:
1. Would subclassing the Engine and overriding the execute function achieve 
this? 
2. Is there a better\recommended approach?

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.


Re: [sqlalchemy] Is there a good ORM tutorial? And advice on parent/child management

2014-01-10 Thread Michael Bayer

On Jan 10, 2014, at 1:42 PM, Paul Moore p.f.mo...@gmail.com wrote:

 On Friday, 10 January 2014 17:52:45 UTC, Michael Bayer wrote:
 there’s various patterns for dealing with the very common issue of “create 
 unique object if not exists, else use the current one”.  One that I 
 frequently point to is the unique object recipe: 
 
 OK, so looking at that seems to imply that
 
 pkg = Package(name=pip)
 session.add(pkg)
 is_it_there = session.query(Package).filter(Package.name == 'pip').first()
 assert is_it_there is pkg
 
 will fail the assertion (unless there is a flush).

if autoflush is turned on, it will pass the assertion.  the Session is flushed 
before any SQL query when autoflush is left at its default of True. So first 
pkg goes in via INSERT, the SELECT is emitted, locates the row with the 
identity of pkg, locates “pkg” itself in the identity map, and returns it.


 Otherwise, I don't see why the unique cache is needed in the recipe you 
 reference.

the cache isn’t needed but is nice so that many objects all doing the same 
thing don’t have to keep hitting the database for an object that’s already 
local in memory.

keep in mind, the Query always emits SQL, except in the case of the get() 
method which will look locally in the identity map first.  Otherwise, as rows 
are returned from the SQL statement, the primary key identity of each row is 
matched to whatever objects are already in the identity map.   That’s how the 
identity map works.   You still get the SQL being emitted in most cases so it’s 
not quite a “cache”.   More detail on this here: 
http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#is-the-session-a-cache



signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] Custom logic for query execution

2014-01-10 Thread Michael Bayer

On Jan 10, 2014, at 1:50 PM, Sylvester Steele sylvesterste...@gmail.com wrote:

 Hi,
 Currently I am using the sqlalchemy engine to execute string queries only. I 
 do plan on using sqlalchemy more extensively (including ORM) in the near 
 future. 
 I need to add retry logic on every query, in case of some database failures 
 (less than ideal, but the server is a bit flaky). 
 
 Questions:
 1. Would subclassing the Engine and overriding the execute function achieve 
 this? 
 2. Is there a better\recommended approach?

technically, there’s no such operation as “retry a query” in the field of 
“database failures”, assuming we’re talking about disconnects.   There’s only, 
“retry a transaction”.  So it’s typically not so simple to build a generic 
“retry query” feature - a disconnect means the whole transaction is gone, so 
whatever state was already built up is gone as well. In this regard 
engine.execute() is kind of hiding a lot of this in that it begins/commits a 
transaction on its own, but for more substantial applications I’d advise having 
your application be aware of the scope of transactions.  Especially if using 
the ORM, it’s pretty much a requirement as the ORM defers/bundles CRUD 
operations into batches.

Unless you never perform two queries in a row, your app will perform much 
better and also will integrate correctly with transaction isolation.I 
typically advise that this scope is managed in just one place, as opposed to 
explicitly boilerplated throughout the application, a common antipattern.

if you’re anticipating frequent database failures, and excepting out is not an 
option, you might want to go with a “pessimistic” listener as that described at 
http://docs.sqlalchemy.org/en/rel_0_9/core/pooling.html#disconnect-handling-pessimistic.



 
 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] Custom logic for query execution

2014-01-10 Thread Claudio Freire
On Fri, Jan 10, 2014 at 3:50 PM, Sylvester Steele
sylvesterste...@gmail.com wrote:
 Hi,
 Currently I am using the sqlalchemy engine to execute string queries only. I
 do plan on using sqlalchemy more extensively (including ORM) in the near
 future.
 I need to add retry logic on every query, in case of some database failures
 (less than ideal, but the server is a bit flaky).

 Questions:
 1. Would subclassing the Engine and overriding the execute function achieve
 this?

Let me first point out, that you cannot consider all queries equal,
and retry-able.

First problem you'll face, is secondary effects. Update and inserts
obviously, but secondary effects hidden in select queries could also
be an issue (say, triggers or something else that has a secondary
effect).

Second problem you'll face are transactions. When a failure occurs,
you usually have no choice to retry a single query, you have to retry
the whole transaction.

So doing it at the Engine level may prove a bad choice with the above in mind.

-- 
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] Custom logic for query execution

2014-01-10 Thread Sylvester Steele
Thanks for you feedback. I will take a look at the pessimistic listener


On Fri, Jan 10, 2014 at 2:02 PM, Michael Bayer mike...@zzzcomputing.comwrote:


 On Jan 10, 2014, at 1:50 PM, Sylvester Steele sylvesterste...@gmail.com
 wrote:

 Hi,
 Currently I am using the sqlalchemy engine to execute string queries only.
 I do plan on using sqlalchemy more extensively (including ORM) in the near
 future.
 I need to add retry logic on every query, in case of some database
 failures (less than ideal, but the server is a bit flaky).

 Questions:
 1. Would subclassing the Engine and overriding the execute function
 achieve this?
 2. Is there a better\recommended approach?


 technically, there’s no such operation as “retry a query” in the field of
 “database failures”, assuming we’re talking about disconnects.   There’s
 only, “retry a transaction”.  So it’s typically not so simple to build a
 generic “retry query” feature - a disconnect means the whole transaction is
 gone, so whatever state was already built up is gone as well. In this
 regard engine.execute() is kind of hiding a lot of this in that it
 begins/commits a transaction on its own, but for more substantial
 applications I’d advise having your application be aware of the scope of
 transactions.  Especially if using the ORM, it’s pretty much a requirement
 as the ORM defers/bundles CRUD operations into batches.

 Unless you never perform two queries in a row, your app will perform much
 better and also will integrate correctly with transaction isolation.I
 typically advise that this scope is managed in just one place, as opposed
 to explicitly boilerplated throughout the application, a common antipattern.

 if you’re anticipating frequent database failures, and excepting out is
 not an option, you might want to go with a “pessimistic” listener as that
 described at

 http://docs.sqlalchemy.org/en/rel_0_9/core/pooling.html#disconnect-handling-pessimistic
 .




 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.




-- 
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] Re: How to stop SQLAlchemy from adding an ON UPDATE clause to a TIMESTAMP column by default

2014-01-10 Thread Steve Johnson
I realize this thread is ancient, but I'm resurrecting it for Googleable 
posterity since I just ran across the same issue.

The problem is that MySQL helpfully inserts the ON UPDATE cheese unless 
you specify a default and/or a NULL/NOT NULL value in the CREATE TABLE 
query.

http://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html

Unfortunately, I haven't yet been able to get sqlalchemy to actually send 
such a query, this being my attempt:

time = Column(
TIMESTAMP(), primary_key=True,
default=datetime.min, nullable=False)

Will reply again if I manage to get a TIMESTAMP column without the ON 
UPDATE stuff.

On Monday, November 28, 2011 5:09:35 PM UTC-8, Michael Bayer wrote:

 There's some more happening on your end.   Rest assured DEFAULT and ON 
 UPDATE are not generated without very specific and explicit instructions - 
 the default and onupdate keywords would need to be passed to your 
 Column - engine arguments have nothing to do with it.If it were me I'd 
 stick a pdb into Column to intercept it happening.


 Here is the output of your program:

 2011-11-28 20:00:28,203 INFO sqlalchemy.engine.base.Engine SELECT 
 DATABASE()
 2011-11-28 20:00:28,203 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,205 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES 
 LIKE 'character_set%%'
 2011-11-28 20:00:28,205 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,206 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES 
 LIKE 'lower_case_table_names'
 2011-11-28 20:00:28,206 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,207 INFO sqlalchemy.engine.base.Engine SHOW COLLATION
 2011-11-28 20:00:28,207 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,211 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES 
 LIKE 'sql_mode'
 2011-11-28 20:00:28,211 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,212 INFO sqlalchemy.engine.base.Engine DESCRIBE `foo`
 2011-11-28 20:00:28,212 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,215 INFO sqlalchemy.engine.base.Engine 
 DROP TABLE foo
 2011-11-28 20:00:28,215 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,215 INFO sqlalchemy.engine.base.Engine COMMIT
 2011-11-28 20:00:28,216 INFO sqlalchemy.engine.base.Engine DESCRIBE `foo`
 2011-11-28 20:00:28,216 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,217 INFO sqlalchemy.engine.base.Engine ROLLBACK
 2011-11-28 20:00:28,217 INFO sqlalchemy.engine.base.Engine 
 CREATE TABLE foo (
 id CHAR(36) NOT NULL, 
 `dateAdded` TIMESTAMP, 
 reason TEXT, 
 PRIMARY KEY (id)
 )


 2011-11-28 20:00:28,217 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,275 INFO sqlalchemy.engine.base.Engine COMMIT

 On Nov 28, 2011, at 5:38 PM, Ben Hayden wrote:

 Hmm... well this is a weird problem then. I ran the provided code, and got 
 the same result you did, with the DEFAULT  ON UPDATE missing. However, I 
 added a couple lines:

 *from sqlalchemy.ext.declarative import declarative_base*
 *from sqlalchemy import Table, CHAR, TIMESTAMP, TEXT, schema, Column*
 *from uuid import uuid4 as uuid*

 *Base = declarative_base()*
 *class Foo(Base):*
 *__tablename__ = 'foo'*

 *#column definitions*
 *id = Column(u'id', CHAR(length=36), default=uuid, primary_key=True, 
 nullable=False)*
 *date_added = Column(u'dateAdded', TIMESTAMP(), nullable=False)*
 *reason = Column(u'reason', TEXT())*

 *from sqlalchemy.dialects import mysql*
 *print schema.CreateTable(Foo.__table__).compile(dialect=mysql.dialect())*
 *Base.metadata.bind = db.generate_engine()*
 *Base.metadata.drop_all()*
 *Base.metadata.create_all()  *


 The create table that was actually generated in the db is still:

 *CREATE TABLE `foo` (*
 *  `id` char(36) NOT NULL,*
 *  `dateAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE 
 CURRENT_TIMESTAMP,*
 *  `reason` text,*
 *  PRIMARY KEY (`id`)*
 *) ENGINE=InnoDB DEFAULT CHARSET=latin1;*

 My generate_engine method is a little helper method that returns an engine 
 with the following params:

 *create_engine('mysql://%s:%s@%s/%s' % (*
 * config.get('database', 'user'),*
 * urllib.quote_plus(config.get('database', 'pass')),*
 * config.get('database', 'host'),*
 * config.get('database', 'name')),*
 * convert_unicode=True, pool_size=20, pool_recycle=60,*
 * connect_args={'use_unicode': True, 'charset': 
 'utf8', 'compress': True})*

 Am I unknowingly passing a default I shouldn't to SQLA that is causing the 
 generation of the table to add those defaults? Or is there an option in 
 MySQL that I unknowingly have turned on?

 My versions:

 Python 2.7
 SQLA 0.7.*
 MySQL version 5.5.11


 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To view this discussion on the web visit 
 

Re: [sqlalchemy] Re: How to stop SQLAlchemy from adding an ON UPDATE clause to a TIMESTAMP column by default

2014-01-10 Thread Steve Johnson
My solution, since sqlalchemy seems to be ignoring the nullable and default 
kwargs, is this:

time = Column(
TIMESTAMP(), primary_key=True,
server_default=text('-00-00 00:00:00'))

The default is just never used.

On Friday, January 10, 2014 12:20:45 PM UTC-8, Steve Johnson wrote:

 I realize this thread is ancient, but I'm resurrecting it for Googleable 
 posterity since I just ran across the same issue.

 The problem is that MySQL helpfully inserts the ON UPDATE cheese unless 
 you specify a default and/or a NULL/NOT NULL value in the CREATE TABLE 
 query.

 http://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html

 Unfortunately, I haven't yet been able to get sqlalchemy to actually send 
 such a query, this being my attempt:

 time = Column(
 TIMESTAMP(), primary_key=True,
 default=datetime.min, nullable=False)

 Will reply again if I manage to get a TIMESTAMP column without the ON 
 UPDATE stuff.

 On Monday, November 28, 2011 5:09:35 PM UTC-8, Michael Bayer wrote:

 There's some more happening on your end.   Rest assured DEFAULT and ON 
 UPDATE are not generated without very specific and explicit instructions - 
 the default and onupdate keywords would need to be passed to your 
 Column - engine arguments have nothing to do with it.If it were me I'd 
 stick a pdb into Column to intercept it happening.


 Here is the output of your program:

 2011-11-28 20:00:28,203 INFO sqlalchemy.engine.base.Engine SELECT 
 DATABASE()
 2011-11-28 20:00:28,203 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,205 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES 
 LIKE 'character_set%%'
 2011-11-28 20:00:28,205 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,206 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES 
 LIKE 'lower_case_table_names'
 2011-11-28 20:00:28,206 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,207 INFO sqlalchemy.engine.base.Engine SHOW COLLATION
 2011-11-28 20:00:28,207 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,211 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES 
 LIKE 'sql_mode'
 2011-11-28 20:00:28,211 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,212 INFO sqlalchemy.engine.base.Engine DESCRIBE `foo`
 2011-11-28 20:00:28,212 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,215 INFO sqlalchemy.engine.base.Engine 
 DROP TABLE foo
 2011-11-28 20:00:28,215 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,215 INFO sqlalchemy.engine.base.Engine COMMIT
 2011-11-28 20:00:28,216 INFO sqlalchemy.engine.base.Engine DESCRIBE `foo`
 2011-11-28 20:00:28,216 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,217 INFO sqlalchemy.engine.base.Engine ROLLBACK
 2011-11-28 20:00:28,217 INFO sqlalchemy.engine.base.Engine 
 CREATE TABLE foo (
 id CHAR(36) NOT NULL, 
 `dateAdded` TIMESTAMP, 
 reason TEXT, 
 PRIMARY KEY (id)
 )


 2011-11-28 20:00:28,217 INFO sqlalchemy.engine.base.Engine ()
 2011-11-28 20:00:28,275 INFO sqlalchemy.engine.base.Engine COMMIT

 On Nov 28, 2011, at 5:38 PM, Ben Hayden wrote:

 Hmm... well this is a weird problem then. I ran the provided code, and 
 got the same result you did, with the DEFAULT  ON UPDATE missing. However, 
 I added a couple lines:

 *from sqlalchemy.ext.declarative import declarative_base*
 *from sqlalchemy import Table, CHAR, TIMESTAMP, TEXT, schema, Column*
 *from uuid import uuid4 as uuid*

 *Base = declarative_base()*
 *class Foo(Base):*
 *__tablename__ = 'foo'*

 *#column definitions*
 *id = Column(u'id', CHAR(length=36), default=uuid, primary_key=True, 
 nullable=False)*
 *date_added = Column(u'dateAdded', TIMESTAMP(), nullable=False)*
 *reason = Column(u'reason', TEXT())*

 *from sqlalchemy.dialects import mysql*
 *print schema.CreateTable(Foo.__table__).compile(dialect=mysql.dialect())*
 *Base.metadata.bind = db.generate_engine()*
 *Base.metadata.drop_all()*
 *Base.metadata.create_all()  *  
  

 The create table that was actually generated in the db is still:

 *CREATE TABLE `foo` (*
 *  `id` char(36) NOT NULL,*
 *  `dateAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE 
 CURRENT_TIMESTAMP,*
 *  `reason` text,*
 *  PRIMARY KEY (`id`)*
 *) ENGINE=InnoDB DEFAULT CHARSET=latin1;*

 My generate_engine method is a little helper method that returns an 
 engine with the following params:

 *create_engine('mysql://%s:%s@%s/%s' % (*
 * config.get('database', 'user'),*
 * urllib.quote_plus(config.get('database', 'pass')),*
 * config.get('database', 'host'),*
 * config.get('database', 'name')),*
 * convert_unicode=True, pool_size=20, 
 pool_recycle=60,*
 * connect_args={'use_unicode': True, 'charset': 
 'utf8', 'compress': True})*

 Am I unknowingly passing a default I shouldn't to SQLA that is causing 
 the generation of the