[sqlalchemy] Eager loading hates single table inheritance

2012-01-09 Thread Yuen Ho Wong
Here's a list of pathological test cases that confuses the hell out of SA 
while trying to eager load more than 1 collections which are mapped to the 
same table using single table inheritance. In short, only joinedload*() 
appears to work out of all the eager loading methods. This pretty much 
means that supplying eager load options to a Query object doesn't mean you 
will always get back the same result.

Ideally, I'd like subqueryload*() and contains_eager() to work just like 
joinedload*() to prevent a situation where I have to waste bandwidth 
loading the same data over and over again or doing MxN queries.

Is there anyway that I can do what I want without rewriting my complicated 
query in full SQL expression?

Thanks!

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/u-PW089d3McJ.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

#! /usr/bin/env python

from sqlalchemy import Column, Integer, Unicode, ForeignKey, Enum, Table, \
create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref, sessionmaker, joinedload, \
joinedload_all, contains_eager, subqueryload, subqueryload_all

Base = declarative_base()
metadata = Base.metadata


class SearchOption(Base):
__tablename__ = searchoption

id = Column(Integer, autoincrement=True, primary_key=True)
parent_id = Column(Integer, ForeignKey(id,
   onupdate=CASCADE,
   ondelete=CASCADE))
parent = relationship(SearchOption, uselist=False, remote_side=[id],
  backref=backref(children))
discriminator = Column(type, Enum(origin, food,
name=searchoptiontype))
__mapper_args__ = {polymorphic_on: discriminator}
displayname = Column(Unicode(64), nullable=False)


class OriginOption(SearchOption):
__mapper_args__ = {polymorphic_identity: origin}


class FoodOption(SearchOption):
__mapper_args__ = {polymorphic_identity: food}


product_searchoption_table = Table(product_searchoption, metadata,
   Column(product_id,
  Integer,
  ForeignKey(product.id,
 onupdate=CASCADE,
 ondelete=CASCADE),
  primary_key=True),
   Column(searchoption_id,
  Integer,
  ForeignKey(searchoption.id,
 onupdate=CASCADE,
 ondelete=CASCADE),
  primary_key=True))


class Product(Base):

__tablename__ = product

id = Column(Integer, autoincrement=True, primary_key=True)

origin = relationship(OriginOption, uselist=False,
  secondary=product_searchoption_table)
foods = relationship(FoodOption,
 secondary=product_searchoption_table)


if __name__ == __main__:
engine = create_engine(postgresql+psycopg2://tester:tester@localhost/test_eagerload,
   echo=True)
Session = sessionmaker(engine)
session = Session()

metadata.create_all(engine)

usa = OriginOption(displayname=uusa)
canada = OriginOption(displayname=ucanada)

apple = FoodOption(displayname=uapple)
orange = FoodOption(displayname=uorange)
banana = FoodOption(displayname=ubanana)

product1 = Product(origin=usa, foods=[apple])
product2 = Product(origin=canada, foods=[orange, banana])
product3 = Product()

session.add(product1)
session.add(product2)
session.add(product3)

session.commit()

session.expunge_all()

# If all the collections to eager load belong to a single table inheritance
# mapping, there's no way to let SA know to optimize this it seems.
p = session.query(Product)\
.options(subqueryload_all(Product.origin, Product.foods))\
.filter(Product.id == 2).one()

assert p.id == 2
assert p.origin.displayname == ucanada # This is only eager loaded by the previous query
assert [f.displayname for f in p.foods] == [u'orange', u'banana'] # This is still lazy loaded

session.expunge_all()

# Now all the collections are eagerly loaded, but extremely inefficient
# because of all the MxN queries
p = session.query(Product)\

Re: [sqlalchemy] Eager loading hates single table inheritance

2012-01-09 Thread Jimmy Yuen Ho Wong
On 10/1/12 12:19 AM, Michael Bayer wrote:
 A common theme in SQLAlchemy is that, despite all the flak we get for being 
 complicated, SQLAlchemy is actually very simple.   It has a handful of 
 constructs which seek to do exactly the same thing in exactly the same way, 
 as consistently as possible.   So we sometimes get requests for SQLAlchemy 
 should figure out XYZ and it's like, well not really, that would be really 
 complicated.
Ah ha don't get me wrong but I didn't say SA was complicated, I said my
actual queries used in production is complicated. What's I've shown you
was just a simplified version of what I've narrowed down. SA sure had a
large surface area to get started because it does so much more, but I've
grown to love it. This is really the first time I tried to do something
complicated like this with SA and I was testing if SA would be smart
about this. I can't really live without SA now.
 you'd use two joinedload() twice for that. So all of the examples where 
 you're distinguishing xyz_all() from xyz(), all the same thing.   

 It's silently ignored now so http://www.sqlalchemy.org/trac/ticket/2370 is 
 added.  If I can get to it in 0.7 it will emit a warning, will raise an error 
 in 0.8.
Ah, thanks for telling me this. Didn't notice this from the docs.
 In the subqueryload_all()/subqueryload() example, you'll note the second one 
 with two separate subqueryload() calls does in fact correctly do the 
 subqueryload twice.   There's no way SQLA would ever figure out 
 automatically that they're against the same table and then join the two 
 queries together, decisionmaking like would be enormously complicated as well 
 as the mechanics of how to get a single loader to coordinate among two 
 relationships.   If you use just one relationship() to SearchOption then 
 provide filtered accessors, then you get exactly the optimization you're 
 looking for.
Is it possible to include a special flag to the subqueryload() call to
tell SA to optimize for this case? SA already knows about the class
hierarchy to be able to distinguish between the classes and how they map
to the rows returned, changing the model mapping is not always feasible.
In fact, if SA could do this, subqueryload() will be the optimal
solution for this use case. joinedload(), even when it works, it's still
too wasteful. Using events will work for now, but it's not as obvious.
SA already is so smart about things, surely it can be smarter no? :P
 Ticket 2120 calls for at least an option nested_joins=True, specifying that 
 the more correct/efficient system of nesting joins should be used.   This is 
 all 0.8 stuff, as the joined eager loading code would be destabilized by this 
 - if it turns out to be an isolated option it could move to 0.7.   Your set 
 of tests here makes me more interested in the issue though so perhaps we'll 
 see if I have time to try some things out.
Does it mean that the only way to eager load reliably in this
many-to-many single table inheritance use case, depending on the data,
is joinedload(innerjoin=True) for uselist=False relationships for now?
In my case, I can just use innerjoin=True all the way, but there may be
cases where the code has to switch between innerjoin and left join
depending on the relationships.

 Finally the contains_eager version.   SQLAlchemy again expects two distinct 
 sets of columns for each relationship, so you must join to the table twice:

 sa1 = aliased(OriginOption)
 sa2 = aliased(FoodOption)

 p = session.query(Product)\
 .join(sa1, Product.origin)\
 .join(sa2, Product.foods)\
 .options(contains_eager(Product.origin, alias=sa1),
  contains_eager(Product.foods, alias=sa2))\
 .filter(Product.id == 2).one()


 Same theme here, you're hoping SQLAlchemy can figure out something in 
 Python, i.e. that only certain rows being routed to 
 Product.origin/Product.foods should be used for each, but it's not that 
 complicated. It relies upon SQL to present it with the correct data 
 geometry and assumes it is correct.  Second-guessing what it gets back from 
 SQL to check, oh is this some special 1% edge case where I might have to 
 filter extra types that I'm not supposed to receive here? wouldn't be 
 efficient or consistent with how everything else works.
 consistently.
Ah thanks for this solution, but again, self joining for each
relationship is too inefficient. The point is, as a user, I think the
query with a single join already contains all the data needed to
reconstruct collections. Plus, I've already told SA that the results
will contain the rows that it can populate the collections with, why
can't it do that? That's the thought that went through my head.

Again, I think if contains_eager() accepts a flag that tells it to
optimize for this case, the code to handle this will be isolated.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To 

Re: [sqlalchemy] Eager loading hates single table inheritance

2012-01-09 Thread Jimmy Yuen Ho Wong
Ah Thanks! A bit of a hack but certainly works for now. Thanks for
helping out. Really appreciate it!

Jimmy Yuen Ho Wong

On 10/1/12 3:31 AM, Michael Bayer wrote:
 On Jan 9, 2012, at 11:19 AM, Michael Bayer wrote:

 The first thing I note here is, if I were doing a model like this, I'd 
 either use two different association tables between Product-Origin and 
 Product-Food, or I'd make one relationship(), and handle the filtering in 
 Python (which is essentially what you're wishing SQLAlchemy did here).   The 
 ORM wants to know about your table relationships which here is just 
 A-assoc-B.All of the issues here, some of which I consider to be SQLA 
 bugs anyway, would go away if you did it in that manner, subqueryloading 
 would be efficient, etc.

 Here's an event that does what you need:

 from sqlalchemy.orm import attributes
 from sqlalchemy import event

 class Product(Base):

 __tablename__ = product

 id = Column(Integer, autoincrement=True, primary_key=True)

 options = relationship(SearchOption, secondary=product_searchoption_table)
 origin = relationship(OriginOption, uselist=False,
   secondary=product_searchoption_table)
 foods = relationship(FoodOption,
  secondary=product_searchoption_table)

 @event.listens_for(Product, load)
 def mything(target, context):
 if 'options' in target.__dict__:
 attributes.set_committed_value(
 target, 'foods',
 [o for o in target.options if o.discriminator=='food']
 )
 origin = [o for o in target.options if o.discriminator=='origin']
 attributes.set_committed_value(
 target, 'origin', 
 origin[0] if origin else None
 )

 # only 2 queries
 for row in session.query(Product).options(subqueryload(Product.options)):
 print row, row.origin, row.foods

 if I added an onload event for individual relationship attributes that would 
 make this event a little more targeted.





-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] order_by with explicit column name messes up subqueryload

2012-01-08 Thread Yuen Ho Wong
Hi,

I have a rather complicated problem and I was wondering if you guys
could help.

So I have a query, session.query(Product, Merchant, d), where Product
is 1-to-many with Merchant, and d is the distance from some lat long.
d is actually a sqlalchemy.sql.label() of some complicated GeoAlchemy
function calls.

Product has a number of collections in which I would like to load
using subqueryload_all() as well, and the result is ordered by
distance as in order_by(distance), where distance is the name of
the label d.

My problem is, since I'm supplying the Query object with an explicit
order_by() name, when I use subqueryload(), the order_by() name is put
into the subquery as is, because SQLAlchemy doesn't know any better
with a plain string. If I pass in a column element, SQLAlchemy seems
to know not to put an ORDER BY in the subquery. This seems to me like
a bug because a subqueryload() always join on the primary key of the
previous SELECT, so unless the name is the primary key name, it really
shouldn't be put in the subquery.

So finally my question, if this is too hard to fix, is there an option
somewhere that I can tell SA to ignore the previous order_by() when
doing a subqueryload()? If not, and I can't wait for a fix now, is
there a way where I can turn my distance label into a ClauseElement so
that SA knows not to put into the subquery when loading collections?

Thanks in advance!

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: order_by with explicit column name messes up subqueryload

2012-01-08 Thread Yuen Ho Wong
BTW, aliased() and alias() don't work on a label() either. I tried
passing the label object straight into the order_by() as well to no
avail. I'm all out of ideas.

On Jan 9, 3:47 am, Yuen Ho Wong wyue...@gmail.com wrote:
 Hi,

 I have a rather complicated problem and I was wondering if you guys
 could help.

 So I have a query, session.query(Product, Merchant, d), where Product
 is 1-to-many with Merchant, and d is the distance from some lat long.
 d is actually a sqlalchemy.sql.label() of some complicated GeoAlchemy
 function calls.

 Product has a number of collections in which I would like to load
 using subqueryload_all() as well, and the result is ordered by
 distance as in order_by(distance), where distance is the name of
 the label d.

 My problem is, since I'm supplying the Query object with an explicit
 order_by() name, when I use subqueryload(), the order_by() name is put
 into the subquery as is, because SQLAlchemy doesn't know any better
 with a plain string. If I pass in a column element, SQLAlchemy seems
 to know not to put an ORDER BY in the subquery. This seems to me like
 a bug because a subqueryload() always join on the primary key of the
 previous SELECT, so unless the name is the primary key name, it really
 shouldn't be put in the subquery.

 So finally my question, if this is too hard to fix, is there an option
 somewhere that I can tell SA to ignore the previous order_by() when
 doing a subqueryload()? If not, and I can't wait for a fix now, is
 there a way where I can turn my distance label into a ClauseElement so
 that SA knows not to put into the subquery when loading collections?

 Thanks in advance!

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: order_by with explicit column name messes up subqueryload

2012-01-08 Thread Yuen Ho Wong
Except that LIMIT and OFFSET are present in my query, gnarly isn't
it ? :P

d = label(distance,
some_complicated_geoalchemy_function_call(columns...))

q = session.query(Product, Merchant.location, d)\
.join(Merchant, Product.merchant_id == Merchant.id)\
.filter(Product.numinstock  0)\
.options(subqueryload_all(Product.origin, Product.style,
Product.foods, Product.flavors, Product.occasions, Product.moods,
Product.varieties))

q = q.order_by(distance).offset(0).limit(20).all()



On Jan 9, 3:57 am, Michael Bayer mike...@zzzcomputing.com wrote:
 On Jan 8, 2012, at 2:47 PM, Yuen Ho Wong wrote:









  Hi,

  I have a rather complicated problem and I was wondering if you guys
  could help.

  So I have a query, session.query(Product, Merchant, d), where Product
  is 1-to-many with Merchant, and d is the distance from some lat long.
  d is actually a sqlalchemy.sql.label() of some complicated GeoAlchemy
  function calls.

  Product has a number of collections in which I would like to load
  using subqueryload_all() as well, and the result is ordered by
  distance as in order_by(distance), where distance is the name of
  the label d.

  My problem is, since I'm supplying the Query object with an explicit
  order_by() name, when I use subqueryload(), the order_by() name is put
  into the subquery as is, because SQLAlchemy doesn't know any better
  with a plain string. If I pass in a column element, SQLAlchemy seems
  to know not to put an ORDER BY in the subquery. This seems to me like
  a bug because a subqueryload() always join on the primary key of the
  previous SELECT, so unless the name is the primary key name, it really
  shouldn't be put in the subquery.

  So finally my question, if this is too hard to fix, is there an option
  somewhere that I can tell SA to ignore the previous order_by() when
  doing a subqueryload()? If not, and I can't wait for a fix now, is
  there a way where I can turn my distance label into a ClauseElement so
  that SA knows not to put into the subquery when loading collections?

 any chance you can save me some time and attach a complete, succinct .py 
 example here ?   subqueryload removes the ORDER BY from the query, provided 
 LIMIT/OFFSET aren't present, unconditionally.  It doesn't care that it's a 
 string or not.

 http://www.sqlalchemy.org/trac/browser/lib/sqlalchemy/orm/strategies

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: order_by with explicit column name messes up subqueryload

2012-01-08 Thread Yuen Ho Wong
Here are the models:

class Merchant(Base):
__tablename__ = merchant
id = Column(Integer, autoincrement=True, primary_key=True)
location = GeometryColumn(Point, nullable=False)

class SearchOption(Base):
__tablename__ = searchoption
id = Column(Integer, autoincrement=True, primary_key=True)
parent_id = Column(Integer, ForeignKey(id,
   onupdate=CASCADE,
   ondelete=CASCADE))
parent = relationship(SearchOption, uselist=False,
remote_side=[id],
  backref=backref(children))
discriminator = Column(type, Enum(style, origin, price,
food,
flavor, occasion,
variety, mood,
name=searchoptiontype))
__mapper_args__ = {polymorphic_on: discriminator}
displayname = Column(Unicode(64), nullable=False)

class StyleOption(SearchOption):
__mapper_args__ = {polymorphic_identity: style}

class OriginOption(SearchOption):
__mapper_args__ = {polymorphic_identity: origin}

class FoodOption(SearchOption):
__mapper_args__ = {polymorphic_identity: food}

class FlavorOption(SearchOption):
__mapper_args__ = {polymorphic_identity: flavor}

class OccasionOption(SearchOption):
__mapper_args__ = {polymorphic_identity: occasion}

class VarietyOption(SearchOption):
__mapper_args__ = {polymorphic_identity: variety}

class MoodOption(SearchOption):
__mapper_args__ = {polymorphic_identity: mood}

product_searchoption_table = Table(product_searchoption, metadata,
   Column(product_id,
  Integer,
  ForeignKey(product.id,
 
onupdate=CASCADE,
 
ondelete=CASCADE),
  primary_key=True),
   Column(searchoption_id,
  Integer,
 
ForeignKey(searchoption.id,
 
onupdate=CASCADE,
 
ondelete=CASCADE),
  primary_key=True))

class Product(Base): # tune full-text search
__tablename__ = product
id = Column(Integer, autoincrement=True, primary_key=True)

origin = relationship(OriginOption, uselist=False,
  secondary=product_searchoption_table)
style = relationship(StyleOption, uselist=False,
 secondary=product_searchoption_table)
pricerange = relationship(PriceOption, uselist=False,
  secondary=product_searchoption_table)
foods = relationship(FoodOption,
 secondary=product_searchoption_table)
flavors = relationship(FlavorOption,
   secondary=product_searchoption_table)
occasions = relationship(OccasionOption,
 secondary=product_searchoption_table)
moods = relationship(MoodOption,
 secondary=product_searchoption_table)
varieties = relationship(VarietyOption,
 secondary=product_searchoption_table)

merchant_id = Column(Integer, ForeignKey(merchant.id,
onupdate=CASCADE,
ondelete=CASCADE),
 nullable=False,)
merchant = relationship(Merchant, uselist=False,
backref=backref(products))


Hope this helps.

On Jan 9, 4:16 am, Yuen Ho Wong wyue...@gmail.com wrote:
 Except that LIMIT and OFFSET are present in my query, gnarly isn't
 it ? :P

     d = label(distance,
 some_complicated_geoalchemy_function_call(columns...))

     q = session.query(Product, Merchant.location, d)\
             .join(Merchant, Product.merchant_id == Merchant.id)\
             .filter(Product.numinstock  0)\
             .options(subqueryload_all(Product.origin, Product.style,
 Product.foods, Product.flavors, Product.occasions, Product.moods,
 Product.varieties))

     q = q.order_by(distance).offset(0).limit(20).all()

 On Jan 9, 3:57 am, Michael Bayer mike...@zzzcomputing.com wrote:







  On Jan 8, 2012, at 2:47 PM, Yuen Ho Wong wrote:

   Hi,

   I have a rather complicated problem and I was wondering if you guys
   could help.

   So I have a query, session.query(Product, Merchant, d), where Product
   is 1-to-many with Merchant, and d is the distance from some lat long.
   d is actually a sqlalchemy.sql.label() of some complicated GeoAlchemy
   function calls.

   Product has a number of collections in which I would like to load
   using subqueryload_all() as well, and the result is ordered by
   distance as in order_by(distance), where distance is the name of
   the label d.

   My problem is, since I'm supplying the Query object with an explicit
   order_by() name, when I use subqueryload(), the order_by() name is put
   into the subquery as is, because SQLAlchemy doesn't know any better
   with a plain string

[sqlalchemy] oursql two phase commit syntax error

2011-06-06 Thread Yuen Ho Wong
I'm testing this on SQLAlchemy 0.7.1, oursql 0.9.2, MySQL 5.5.13 on
Mac OS X 10.6.7

Here's my test script:


from sqlalchemy import create_engine, Column, Integer, Unicode
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker

Base = declarative_base()

class User(Base):
__tablename__ = 'user'
id = Column(Integer, autoincrement=True, primary_key=True)
name = Column(Unicode(128), nullable=False, unique=True)

class Address(Base):
__tablename__ = 'address'
id = Column(Integer, autoincrement=True, primary_key=True)
address = Column(Unicode(128), nullable=False, unique=True)

engine = create_engine(mysql+oursql://tester:tester@localhost/
test_hometasty?charset=utf8)

engine_bindings = {User: engine, Address: engine}

User.metadata.create_all(engine)
Address.metadata.create_all(engine)

Session = scoped_session(sessionmaker(twophase=True))
Session.configure(binds=session_bindings)
Session.configure(binds=engine_bindings)
session = Session()
alice = User(name=ualice)
session.add(alice)
hk = Address(address=uHong Kong)
session.add(hk)
session.commit()


Here's the error I get:

sqlalchemy.exc.ProgrammingError: (ProgrammingError) (1064, 'You have
an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near
\'_sa_7fd8e09924568e2e2a653185227c2929\' at line 1', None) 'XA BEGIN
_sa_7fd8e09924568e2e2a653185227c2929' ()


Am I doing something wrong or is this a bug?

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: oursql two phase commit syntax error

2011-06-06 Thread Yuen Ho Wong
Ah it seems that this bug only happens with sql-mode = ANSI set in
my.cnf. This doesn't seem to be an issue with the mysql-python driver
tho.


On Jun 7, 2:57 am, Michael Bayer mike...@zzzcomputing.com wrote:
 On Jun 6, 2011, at 2:23 PM, Yuen Ho Wong wrote:





  I'm testing this on SQLAlchemy 0.7.1, oursql 0.9.2, MySQL 5.5.13 on
  Mac OS X 10.6.7

  Here's my test script:

  from sqlalchemy import create_engine, Column, Integer, Unicode
  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy.orm import scoped_session, sessionmaker

  Base = declarative_base()

  class User(Base):
     __tablename__ = 'user'
     id = Column(Integer, autoincrement=True, primary_key=True)
     name = Column(Unicode(128), nullable=False, unique=True)

  class Address(Base):
     __tablename__ = 'address'
     id = Column(Integer, autoincrement=True, primary_key=True)
     address = Column(Unicode(128), nullable=False, unique=True)

  engine = create_engine(mysql+oursql://tester:tester@localhost/
  test_hometasty?charset=utf8)

  engine_bindings = {User: engine, Address: engine}

  User.metadata.create_all(engine)
  Address.metadata.create_all(engine)

  Session = scoped_session(sessionmaker(twophase=True))
  Session.configure(binds=session_bindings)
  Session.configure(binds=engine_bindings)
  session = Session()
  alice = User(name=ualice)
  session.add(alice)
  hk = Address(address=uHong Kong)
  session.add(hk)
  session.commit()

 you might want to check that you're on MySQL 5.5 on all systems - the script 
 works for me, provided I comment out the non-existent session_bindings 
 variable.

 my output is below:

 2011-06-06 14:56:37,278 INFO sqlalchemy.engine.base.Engine
 CREATE TABLE address (
         id INTEGER NOT NULL AUTO_INCREMENT,
         address VARCHAR(128) NOT NULL,
         PRIMARY KEY (id),
         UNIQUE (address)
 )

 2011-06-06 14:56:37,278 INFO sqlalchemy.engine.base.Engine ()
 2011-06-06 14:56:37,279 INFO sqlalchemy.engine.base.Engine COMMIT
 2011-06-06 14:56:37,280 INFO sqlalchemy.engine.base.Engine
 CREATE TABLE user (
         id INTEGER NOT NULL AUTO_INCREMENT,
         name VARCHAR(128) NOT NULL,
         PRIMARY KEY (id),
         UNIQUE (name)
 )

 2011-06-06 14:56:37,280 INFO sqlalchemy.engine.base.Engine ()
 2011-06-06 14:56:37,281 INFO sqlalchemy.engine.base.Engine COMMIT
 2011-06-06 14:56:37,281 INFO sqlalchemy.engine.base.Engine DESCRIBE `address`
 2011-06-06 14:56:37,281 INFO sqlalchemy.engine.base.Engine ()
 2011-06-06 14:56:37,282 INFO sqlalchemy.engine.base.Engine DESCRIBE `user`
 2011-06-06 14:56:37,282 INFO sqlalchemy.engine.base.Engine ()
 2011-06-06 14:56:37,285 INFO sqlalchemy.engine.base.Engine XA BEGIN 
 _sa_9121998e519e1b3edb13e0aa440ca7c7
 2011-06-06 14:56:37,285 INFO sqlalchemy.engine.base.Engine ()
 2011-06-06 14:56:37,286 INFO sqlalchemy.engine.base.Engine INSERT INTO 
 address (address) VALUES (?)
 2011-06-06 14:56:37,286 INFO sqlalchemy.engine.base.Engine (u'Hong Kong',)
 2011-06-06 14:56:37,287 INFO sqlalchemy.engine.base.Engine INSERT INTO user 
 (name) VALUES (?)
 2011-06-06 14:56:37,287 INFO sqlalchemy.engine.base.Engine (u'alice',)
 2011-06-06 14:56:37,287 INFO sqlalchemy.engine.base.Engine XA END 
 _sa_9121998e519e1b3edb13e0aa440ca7c7
 2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine ()
 2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine XA PREPARE 
 _sa_9121998e519e1b3edb13e0aa440ca7c7
 2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine ()
 2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine XA COMMIT 
 _sa_9121998e519e1b3edb13e0aa440ca7c7
 2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine ()





  Here's the error I get:

  sqlalchemy.exc.ProgrammingError: (ProgrammingError) (1064, 'You have
  an error in your SQL syntax; check the manual that corresponds to your
  MySQL server version for the right syntax to use near
  \'_sa_7fd8e09924568e2e2a653185227c2929\' at line 1', None) 'XA BEGIN
  _sa_7fd8e09924568e2e2a653185227c2929' ()

  Am I doing something wrong or is this a bug?

  --
  You received this message because you are subscribed to the Google Groups 
  sqlalchemy group.
  To post to this group, send email to sqlalchemy@googlegroups.com.
  To unsubscribe from this group, send email to 
  sqlalchemy+unsubscr...@googlegroups.com.
  For more options, visit this group 
  athttp://groups.google.com/group/sqlalchemy?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: oursql two phase commit syntax error

2011-06-06 Thread Yuen Ho Wong
Replace the double quotes around the %s with single quotes seems to
have solved the problem with either default SQL MODE or ANSI_QUOTES
set.

Thanks for the helping!


On Jun 7, 3:25 am, Yuen Ho Wong wyue...@gmail.com wrote:
 Ah it seems that this bug only happens with sql-mode = ANSI set in
 my.cnf. This doesn't seem to be an issue with the mysql-python driver
 tho.

 On Jun 7, 2:57 am, Michael Bayer mike...@zzzcomputing.com wrote:



  On Jun 6, 2011, at 2:23 PM, Yuen Ho Wong wrote:

   I'm testing this on SQLAlchemy 0.7.1, oursql 0.9.2, MySQL 5.5.13 on
   Mac OS X 10.6.7

   Here's my test script:

   from sqlalchemy import create_engine, Column, Integer, Unicode
   from sqlalchemy.ext.declarative import declarative_base
   from sqlalchemy.orm import scoped_session, sessionmaker

   Base = declarative_base()

   class User(Base):
      __tablename__ = 'user'
      id = Column(Integer, autoincrement=True, primary_key=True)
      name = Column(Unicode(128), nullable=False, unique=True)

   class Address(Base):
      __tablename__ = 'address'
      id = Column(Integer, autoincrement=True, primary_key=True)
      address = Column(Unicode(128), nullable=False, unique=True)

   engine = create_engine(mysql+oursql://tester:tester@localhost/
   test_hometasty?charset=utf8)

   engine_bindings = {User: engine, Address: engine}

   User.metadata.create_all(engine)
   Address.metadata.create_all(engine)

   Session = scoped_session(sessionmaker(twophase=True))
   Session.configure(binds=session_bindings)
   Session.configure(binds=engine_bindings)
   session = Session()
   alice = User(name=ualice)
   session.add(alice)
   hk = Address(address=uHong Kong)
   session.add(hk)
   session.commit()

  you might want to check that you're on MySQL 5.5 on all systems - the 
  script works for me, provided I comment out the non-existent 
  session_bindings variable.

  my output is below:

  2011-06-06 14:56:37,278 INFO sqlalchemy.engine.base.Engine
  CREATE TABLE address (
          id INTEGER NOT NULL AUTO_INCREMENT,
          address VARCHAR(128) NOT NULL,
          PRIMARY KEY (id),
          UNIQUE (address)
  )

  2011-06-06 14:56:37,278 INFO sqlalchemy.engine.base.Engine ()
  2011-06-06 14:56:37,279 INFO sqlalchemy.engine.base.Engine COMMIT
  2011-06-06 14:56:37,280 INFO sqlalchemy.engine.base.Engine
  CREATE TABLE user (
          id INTEGER NOT NULL AUTO_INCREMENT,
          name VARCHAR(128) NOT NULL,
          PRIMARY KEY (id),
          UNIQUE (name)
  )

  2011-06-06 14:56:37,280 INFO sqlalchemy.engine.base.Engine ()
  2011-06-06 14:56:37,281 INFO sqlalchemy.engine.base.Engine COMMIT
  2011-06-06 14:56:37,281 INFO sqlalchemy.engine.base.Engine DESCRIBE 
  `address`
  2011-06-06 14:56:37,281 INFO sqlalchemy.engine.base.Engine ()
  2011-06-06 14:56:37,282 INFO sqlalchemy.engine.base.Engine DESCRIBE `user`
  2011-06-06 14:56:37,282 INFO sqlalchemy.engine.base.Engine ()
  2011-06-06 14:56:37,285 INFO sqlalchemy.engine.base.Engine XA BEGIN 
  _sa_9121998e519e1b3edb13e0aa440ca7c7
  2011-06-06 14:56:37,285 INFO sqlalchemy.engine.base.Engine ()
  2011-06-06 14:56:37,286 INFO sqlalchemy.engine.base.Engine INSERT INTO 
  address (address) VALUES (?)
  2011-06-06 14:56:37,286 INFO sqlalchemy.engine.base.Engine (u'Hong Kong',)
  2011-06-06 14:56:37,287 INFO sqlalchemy.engine.base.Engine INSERT INTO user 
  (name) VALUES (?)
  2011-06-06 14:56:37,287 INFO sqlalchemy.engine.base.Engine (u'alice',)
  2011-06-06 14:56:37,287 INFO sqlalchemy.engine.base.Engine XA END 
  _sa_9121998e519e1b3edb13e0aa440ca7c7
  2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine ()
  2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine XA PREPARE 
  _sa_9121998e519e1b3edb13e0aa440ca7c7
  2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine ()
  2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine XA COMMIT 
  _sa_9121998e519e1b3edb13e0aa440ca7c7
  2011-06-06 14:56:37,288 INFO sqlalchemy.engine.base.Engine ()

   Here's the error I get:

   sqlalchemy.exc.ProgrammingError: (ProgrammingError) (1064, 'You have
   an error in your SQL syntax; check the manual that corresponds to your
   MySQL server version for the right syntax to use near
   \'_sa_7fd8e09924568e2e2a653185227c2929\' at line 1', None) 'XA BEGIN
   _sa_7fd8e09924568e2e2a653185227c2929' ()

   Am I doing something wrong or is this a bug?

   --
   You received this message because you are subscribed to the Google Groups 
   sqlalchemy group.
   To post to this group, send email to sqlalchemy@googlegroups.com.
   To unsubscribe from this group, send email to 
   sqlalchemy+unsubscr...@googlegroups.com.
   For more options, visit this group 
   athttp://groups.google.com/group/sqlalchemy?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options

[sqlalchemy] How to get the instance back from a PropComparator?

2009-09-27 Thread Yuen Ho Wong

So I have this following code:

class User(Base):


class AgeComparator(PropComparator):

def __lt__(self, other):
pass

def __gt__(self, other):
pass

def __eq__(self, other):
pass

def __ne__(self, other):
return not (self == other)

def __le__(self, other):
return self  other or self == other

def __ge__(self, other):
return self  other or self == other

@comparable_using(AgeComparator)
@property
def age(self):
today = date.today()
age = today - (self.date_of_birth or (today + 1))
return age.days / 365

All I want to do is this:

user = User(date_of_birth=date.today())
session.add(user)
new_borns = session.query(User).filter(User.age == 0).all()

The doc for comparable_property() suggests that this is possible, but
I'm lost finding my way to call the descriptor bound on this instance.

The problem I have is that the ComparableProperty only gave itself and
the mapper to the comparator, but the user instance is nowhere to be
found inside either ComparableProperty, PropComparator or mapper. I'd
appreciate some help here if this is at all possible. The documents on
this is a little too sparse IMO.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: How to get the instance back from a PropComparator?

2009-09-27 Thread Yuen Ho Wong

Ah ha, so SQL expression operations are all translated directly to
their appropriate SQL clauses. This makes sense I guess. Too bad this
means I have to implement the same function twice, one in Python and
another in SQL. Would be nice if there was some magic to morph custom
properties to have some capabilities to operate on the Python side,
but I guess that would be much slower.

Right now I solved this problem with this new comparator:

class AgeComparator(PropComparator):

def __clause_element__(self):
return (func.datediff(func.curdate(),
self.mapper.c.date_of_birth) / 365)

def operate(self, op, *args, **kwargs):
return op(self.__clause_element__(), *args, **kwargs)

Thanks a lot!


On Sep 27, 1:14 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Sep 27, 2009, at 12:49 PM, Yuen Ho Wong wrote:







  So I have this following code:

  class User(Base):
      

      class AgeComparator(PropComparator):

      def __lt__(self, other):
          pass

      def __gt__(self, other):
          pass

      def __eq__(self, other):
          pass

      def __ne__(self, other):
          return not (self == other)

      def __le__(self, other):
          return self  other or self == other

      def __ge__(self, other):
          return self  other or self == other

      @comparable_using(AgeComparator)
      @property
      def age(self):
          today = date.today()
          age = today - (self.date_of_birth or (today + 1))
          return age.days / 365

  All I want to do is this:

  user = User(date_of_birth=date.today())
  session.add(user)
  new_borns = session.query(User).filter(User.age == 0).all()

  The doc for comparable_property() suggests that this is possible, but
  I'm lost finding my way to call the descriptor bound on this instance.

 The age(self): function is only called when you actually have an  
 instance, such as:

 user = sess.query(User).get(10)
 print age is:  , user.age

 The point of @comparable_using associates the behavior of  
 AgeComparator to the age attribute on the User class, no instance:

 User.age == 0

 User.age == 0 is going to invoke the __eq__() method on the  
 AgeComparator you created.  There is no instance within the query()  
 call here.   __eq__() needs to return a clause expression of your  
 choosing, which must be expressed in terms of SQL functions, since  
 you're rendering a SQL statement.   That's a little tricky here since  
 there's a lot of date arithmetic there, but using hypothetical  
 functions it would look something like:

 def __eq__(self, other):
     return func.count_days(func.date_diff(func.now() -  
 mapped_table.c.date_of_birth)) / 365

 The comparable_using example should probably include a short  
 PropComparator to give more context.  A sample comparator is at:

 http://www.sqlalchemy.org/docs/05/mappers.html#custom-comparators





  The problem I have is that the ComparableProperty only gave itself and
  the mapper to the comparator, but the user instance is nowhere to be
  found inside either ComparableProperty, PropComparator or mapper. I'd
  appreciate some help here if this is at all possible. The documents on
  this is a little too sparse IMO.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---