- edited description
Single table polymorphic count issue
Issue #3177
resolved
Originally posted at StackOverflow
When using a polymorphic identity and attempting to count the number of records, incorrect SQL is generated. This SQL will count the entire table rather than the items matching the polymorphic discriminator.
Iterating all the results works as expected, I've only experienced this bug using .count()
.
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Table, Column, Unicode, Integer, create_engine, MetaData, func
from sqlalchemy.orm import scoped_session, sessionmaker
metadata = MetaData()
Base = declarative_base(metadata=metadata)
widgets = Table(
'widgets', metadata,
Column('id', Integer, primary_key=True),
Column('type', Unicode),
Column('state', Unicode)
)
class Widget(Base):
__table__ = widgets
class types(object):
FOO_WIDGET = 'foo'
BAR_WIDGET = 'bar'
__mapper_args__ = {
'polymorphic_on': widgets.c.type,
}
class FooWidget(Widget):
__mapper_args__ = {
'polymorphic_identity': Widget.types.FOO_WIDGET
}
db_engine = create_engine('sqlite:///:memory:', echo=True)
Session = scoped_session(sessionmaker())
Session.configure(bind=db_engine)
metadata.create_all(db_engine)
items = Session.query(FooWidget.id).filter_by(
state='new'
)
print str(items)
print 'i expect the next statement to print something approximating:'
print '''
select count(*) from widgets where type = 'foo' and state = 'new'
'''
print items.count()
# What this actually prints
'''
2014-08-28 09:55:15,055 INFO sqlalchemy.engine.base.Engine SELECT count(*) AS count_1
FROM widgets, (SELECT widgets.id AS widgets_id
FROM widgets
WHERE widgets.state = ?) AS anon_1
WHERE widgets.type IN (?)
'''
Comments (6)
-
reporter -
repo owner When using count() you should be giving it the full entity you are counting. count() was never intended to work the way you are using it so this is something new.
-
repo owner - changed status to resolved
- Changed the approach by which the "single inheritance criterion"
is applied, when using :meth:
.Query.from_self
, or its common user :meth:.Query.count
. The criteria to limit rows to those with a certain type is now indicated on the inside subquery, not the outside one, so that even if the "type" column is not available in the columns clause, we can filter on it on the "inner" query. fixes#3177
→ <<cset fbcb056d90f4>>
-
repo owner good timing as we're able to put major things into 1.0. (this is a fairly major change). was definitely a bug
-
repo owner -
reporter you're a machine @zzzeek. I have no idea how you continue to respond so quickly to so many queries :)
- Log in to comment