Re: [sqlalchemy] column_property for correlated subquery

2013-03-19 Thread Michael Bayer
I think we need to just get column_property to work as a string with 
declarative. 

Sent from my iPhone

On Mar 19, 2013, at 6:10 AM, millerdev miller...@gmail.com wrote:

 __declare_last__ works. Thanks Mike.
 
 Would it make sense to add a property decorator similar to @declared_attr 
 (maybe @declared_last)? Aesthetically, it seems nicer to define each property 
 separately than to pile them all inside a __declared_last__ function. Of 
 course that could introduce a new ordering problem, so __declared_last__ 
 would still be necessary in cases where the properties must to be defined in 
 a particular order (I don't have that situation now, but can imagine it).
 
 ~ Daniel
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+unsubscr...@googlegroups.com.
 To post to this group, send email to sqlalchemy@googlegroups.com.
 Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
 For more options, visit https://groups.google.com/groups/opt_out.
  
  

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




[sqlalchemy] column_property for correlated subquery

2013-03-18 Thread millerdev
Hi,

Using declarative here, and I'm trying to create a column_property with a 
correlated subquery that returns a count of records with a matching value 
in some other column. Here's what I've tried. Option 1 is the best, option 
2 is ugly but second best, option 3 is not a good option since there are 
many other classes involved and the place where I'd need to put that code 
is far away from where it logically belongs.

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

Base = declarative_base()
option = 1

class Foo(Base):
__tablename__ = 'foo'
id = Column(Integer, primary_key=True)
bar_id = Column(Integer, ForeignKey(bar.id))
name = Column(String)

if option == 1:
# does not work (see first traceback below)
@declared_attr
def name_count(cls):
clx = aliased(cls)
return column_property(
select(func.count([clx.id]))
.where(clx.name == cls.name)
.correlate(cls.__table__))

if option == 2:
# does not work (see second traceback below)
_foo = aliased(Foo)
Foo.name_count = column_property(
select([func.count(_foo.id)])
.where(_foo.name == Foo.name)
.correlate(Foo.__table__))


class Bar(Base):
__tablename__ = 'bar'
id = Column(Integer, primary_key=True)
name = Column(String)


if option == 3:
# works, but really not where I want to put this code
_foo = aliased(Foo)
Foo.name_count = column_property(
select([func.count(_foo.id)])
.where(_foo.name == Foo.name)
.correlate(Foo.__table__))


Option 1 traceback:

Traceback (most recent call last):
  File temp/example.py, line 8, in module
class Foo(Base):
  File .../python2.7/site-packages/sqlalchemy/ext/declarative.py, line 
1348, in __init__
_as_declarative(cls, classname, cls.__dict__)
  File .../python2.7/site-packages/sqlalchemy/ext/declarative.py, line 
1181, in _as_declarative
value = getattr(cls, k)
  File .../python2.7/site-packages/sqlalchemy/ext/declarative.py, line 
1554, in __get__
return desc.fget(cls)
  File temp/example.py, line 15, in name_count
clx = aliased(cls)
  File .../python2.7/site-packages/sqlalchemy/orm/util.py, line 385, in 
aliased
return AliasedClass(element, alias=alias, name=name, 
adapt_on_names=adapt_on_names)
  File .../python2.7/site-packages/sqlalchemy/orm/util.py, line 298, in 
__init__
self.__mapper = _class_to_mapper(cls)
  File .../python2.7/site-packages/sqlalchemy/orm/util.py, line 673, in 
_class_to_mapper
raise exc.UnmappedClassError(class_or_mapper)
sqlalchemy.orm.exc.UnmappedClassError: Class '__main__.Foo' is not mapped


Option 2 traceback:

Traceback (most recent call last):
  File temp/example.py, line 16, in module
select([func.count(_foo.id)])
  File .../python2.7/site-packages/sqlalchemy/sql/expression.py, line 
1229, in __call__
return func(*c, **o)
  File .../python2.7/site-packages/sqlalchemy/sql/functions.py, line 16, 
in __call__
args = [_literal_as_binds(c) for c in args]
  File .../python2.7/site-packages/sqlalchemy/sql/expression.py, line 
1440, in _literal_as_binds
return element.__clause_element__()
  File .../python2.7/site-packages/sqlalchemy/orm/attributes.py, line 
117, in __clause_element__
return self.comparator.__clause_element__()
  File .../python2.7/site-packages/sqlalchemy/util/langhelpers.py, line 
506, in oneshot
result = self.fget(obj, *args, **kw)
  File .../python2.7/site-packages/sqlalchemy/orm/properties.py, line 
156, in __clause_element__
return self.adapter(self.prop.columns[0])
  File .../python2.7/site-packages/sqlalchemy/orm/util.py, line 334, in 
__adapt_element
return self.__adapter.traverse(elem).\
  File .../python2.7/site-packages/sqlalchemy/sql/visitors.py, line 185, 
in traverse
return replacement_traverse(obj, self.__traverse_options__, replace)
  File .../python2.7/site-packages/sqlalchemy/sql/visitors.py, line 281, 
in replacement_traverse
obj = clone(obj, **opts)
  File .../python2.7/site-packages/sqlalchemy/sql/visitors.py, line 270, 
in clone
newelem = replace(elem)
  File .../python2.7/site-packages/sqlalchemy/sql/visitors.py, line 182, 
in replace
e = v.replace(elem)
  File .../python2.7/site-packages/sqlalchemy/sql/util.py, line 720, in 
replace
return self._corresponding_column(col, True)
  File .../python2.7/site-packages/sqlalchemy/sql/util.py, line 695, in 
_corresponding_column
require_embedded=require_embedded)
  File .../python2.7/site-packages/sqlalchemy/sql/expression.py, line 
2492, in corresponding_column
if self.c.contains_column(column):
  File .../python2.7/site-packages/sqlalchemy/util/langhelpers.py, line 
485, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
  File 

Re: [sqlalchemy] column_property for correlated subquery

2013-03-18 Thread Michael Bayer
the typical hook for this kind of thing is __declare_last__, works after 
everything has been compiled.

you might have an easier time also (or might not matter) if you build against 
the Table (i.e. Foo.__table__.alias(), etc.) instead of firing up the class 
with aliased(Foo), but if you're in __declare_last__ might not matter anyway.


On Mar 18, 2013, at 12:20 PM, millerdev miller...@gmail.com wrote:

 Hi,
 
 Using declarative here, and I'm trying to create a column_property with a 
 correlated subquery that returns a count of records with a matching value in 
 some other column. Here's what I've tried. Option 1 is the best, option 2 is 
 ugly but second best, option 3 is not a good option since there are many 
 other classes involved and the place where I'd need to put that code is far 
 away from where it logically belongs.
 
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import *
 from sqlalchemy.ext.declarative import declared_attr
 
 Base = declarative_base()
 option = 1
 
 class Foo(Base):
 __tablename__ = 'foo'
 id = Column(Integer, primary_key=True)
 bar_id = Column(Integer, ForeignKey(bar.id))
 name = Column(String)
 
 if option == 1:
 # does not work (see first traceback below)
 @declared_attr
 def name_count(cls):
 clx = aliased(cls)
 return column_property(
 select(func.count([clx.id]))
 .where(clx.name == cls.name)
 .correlate(cls.__table__))
 
 if option == 2:
 # does not work (see second traceback below)
 _foo = aliased(Foo)
 Foo.name_count = column_property(
 select([func.count(_foo.id)])
 .where(_foo.name == Foo.name)
 .correlate(Foo.__table__))
 
 
 class Bar(Base):
 __tablename__ = 'bar'
 id = Column(Integer, primary_key=True)
 name = Column(String)
 
 
 if option == 3:
 # works, but really not where I want to put this code
 _foo = aliased(Foo)
 Foo.name_count = column_property(
 select([func.count(_foo.id)])
 .where(_foo.name == Foo.name)
 .correlate(Foo.__table__))
 
 
 Option 1 traceback:
 
 Traceback (most recent call last):
   File temp/example.py, line 8, in module
 class Foo(Base):
   File .../python2.7/site-packages/sqlalchemy/ext/declarative.py, line 
 1348, in __init__
 _as_declarative(cls, classname, cls.__dict__)
   File .../python2.7/site-packages/sqlalchemy/ext/declarative.py, line 
 1181, in _as_declarative
 value = getattr(cls, k)
   File .../python2.7/site-packages/sqlalchemy/ext/declarative.py, line 
 1554, in __get__
 return desc.fget(cls)
   File temp/example.py, line 15, in name_count
 clx = aliased(cls)
   File .../python2.7/site-packages/sqlalchemy/orm/util.py, line 385, in 
 aliased
 return AliasedClass(element, alias=alias, name=name, 
 adapt_on_names=adapt_on_names)
   File .../python2.7/site-packages/sqlalchemy/orm/util.py, line 298, in 
 __init__
 self.__mapper = _class_to_mapper(cls)
   File .../python2.7/site-packages/sqlalchemy/orm/util.py, line 673, in 
 _class_to_mapper
 raise exc.UnmappedClassError(class_or_mapper)
 sqlalchemy.orm.exc.UnmappedClassError: Class '__main__.Foo' is not mapped
 
 
 Option 2 traceback:
 
 Traceback (most recent call last):
   File temp/example.py, line 16, in module
 select([func.count(_foo.id)])
   File .../python2.7/site-packages/sqlalchemy/sql/expression.py, line 1229, 
 in __call__
 return func(*c, **o)
   File .../python2.7/site-packages/sqlalchemy/sql/functions.py, line 16, in 
 __call__
 args = [_literal_as_binds(c) for c in args]
   File .../python2.7/site-packages/sqlalchemy/sql/expression.py, line 1440, 
 in _literal_as_binds
 return element.__clause_element__()
   File .../python2.7/site-packages/sqlalchemy/orm/attributes.py, line 117, 
 in __clause_element__
 return self.comparator.__clause_element__()
   File .../python2.7/site-packages/sqlalchemy/util/langhelpers.py, line 
 506, in oneshot
 result = self.fget(obj, *args, **kw)
   File .../python2.7/site-packages/sqlalchemy/orm/properties.py, line 156, 
 in __clause_element__
 return self.adapter(self.prop.columns[0])
   File .../python2.7/site-packages/sqlalchemy/orm/util.py, line 334, in 
 __adapt_element
 return self.__adapter.traverse(elem).\
   File .../python2.7/site-packages/sqlalchemy/sql/visitors.py, line 185, in 
 traverse
 return replacement_traverse(obj, self.__traverse_options__, replace)
   File .../python2.7/site-packages/sqlalchemy/sql/visitors.py, line 281, in 
 replacement_traverse
 obj = clone(obj, **opts)
   File .../python2.7/site-packages/sqlalchemy/sql/visitors.py, line 270, in 
 clone
 newelem = replace(elem)
   File .../python2.7/site-packages/sqlalchemy/sql/visitors.py, line 182, in 
 replace
 e = v.replace(elem)
   File