Hi everybody,

After switching from SQLAlchemy 0.6.5 to 0.7.0 we have observed a
problem with such an example code:

(copy at http://ideone.com/WB36Y)
==============================================================
# Fails with Python-2.7.1 and SQLAlchemy-0.7.0
# 

import sqlalchemy
import sqlalchemy.ext.declarative

Base = sqlalchemy.ext.declarative.declarative_base()

class LimitingQuery(sqlalchemy.orm.query.Query):
    
    def get(self, ident):
        # override get() so that the flag is always checked in the 
        # DB as opposed to pulling from the identity map. - this is
optional.
        return sqlalchemy.orm.query.Query.get(self.populate_existing(),
ident)
    
    def __iter__(self):
        return sqlalchemy.orm.query.Query.__iter__(self.private())

    def private(self):
        crit = (self._mapper_zero().class_.isDeleted == False)
        
        return self.enable_assertions(False).filter(crit)

engine = sqlalchemy.create_engine('sqlite:///:memory:', echo = False)

session = sqlalchemy.orm.scoped_session(
    sqlalchemy.orm.sessionmaker(
        bind = engine,
        autocommit = False,
        query_cls = LimitingQuery
    )
)

Base.metadata.bind = engine

class Employee(Base):
    __tablename__ = "employees"
    Id = sqlalchemy.Column( sqlalchemy.types.Integer, primary_key=True,
autoincrement=True)
    isDeleted = sqlalchemy.Column( sqlalchemy.types.Boolean(), default =
False)
    name = sqlalchemy.Column(sqlalchemy.types.String(128))
    managerId = sqlalchemy.Column(sqlalchemy.types.Integer,
sqlalchemy.ForeignKey(Id))
    manager = sqlalchemy.orm.relation(
        'Employee',
        backref = sqlalchemy.orm.backref('subordinates', lazy =
'dynamic'),
        primaryjoin = managerId == Id,
        remote_side = Id
    )

Base.metadata.create_all()

SteveBallmer = Employee(name = 'Steve Ballmer')
CraigMundie = Employee(name = 'Craig Mundie')
BillGates = Employee(name = 'Bill Gates')

session.add_all((SteveBallmer, CraigMundie, BillGates))

BillGates.subordinates = [SteveBallmer, CraigMundie]

# this line:
print BillGates.subordinates.count()
# raises:
# Traceback (most recent call last):
#   File "count_problem.py", line 60, in <module>
#     print BillGates.subordinates.count()
#   File
"/home/filip/tefnet/teferp/workspace/tefobjects/lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7.egg/sqlalchemy/orm/dynamic.py",
 line 251, in count
#     return self._clone(sess).count()
#   File
"/home/filip/tefnet/teferp/workspace/tefobjects/lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7.egg/sqlalchemy/orm/query.py",
 line 2123, in count
#     return self.from_self(col).scalar()
#   File
"/home/filip/tefnet/teferp/workspace/tefobjects/lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7.egg/sqlalchemy/orm/query.py",
 line 1775, in scalar
#     ret = self.one()
#   File
"/home/filip/tefnet/teferp/workspace/tefobjects/lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7.egg/sqlalchemy/orm/query.py",
 line 1744, in one
#     ret = list(self)
#   File "count_problem.py", line 17, in __iter__
#     return sqlalchemy.orm.query.Query.__iter__(self.private())
#   File "count_problem.py", line 20, in private
#     crit = (self._mapper_zero().class_.isDeleted == False)
# AttributeError: 'NoneType' object has no attribute 'class_'
==============================================================

As far as I could debug it the problem starts when count() creates a new
query with the old one as a subquery (but I could very well be wrong).

A similar recipe can be found here:
http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery

Could you give me a hint about a proper way to do this?

regards,
Filip Zyzniewski
Tefnet

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

Reply via email to