SQLAlchemy使用polymorphic_identity为计数生成一个不同的查询

时间:2014-08-09 19:05:50

标签: python sqlalchemy

我有一个我创建的查询,它看起来像

items = Session.query(Widgets.id).filter_by(
    state=WidgetStates.NEW
)

当我查看它的str表示时,我将其视为计划查询

str(items)

'SELECT widgets.id AS widgets_guid \nFROM widgets \nWHERE widgets.state = %(state_1)s'

但是,当我执行查询以获取echo=True的计数时,我看到正在执行不同的查询:

items.count()

2014-08-09 11:59:48,875 INFO sqlalchemy.engine.base.Engine SELECT count(*) AS count_1 
FROM widgets, (SELECT widgets.id AS widgets_id                                       
FROM widgets                                                                           
WHERE widgets.state = %(state_1)s) AS anon_1                                           
WHERE widgets.type IN (%(type_1)s)                                                                        

问题是它会计算type等于" FOO_WIDGET"的整个小部件表。但它不会按照我预期的那样按state来过滤计数。

我认为该问题与应用了polymorphic_identity鉴别器的Widget模型有关:

class Widget(Model):

    class types(object):
        FOO_WIDGET = 'foo'

    __mapper_args__ = {
        'polymorphic_identity': Widget.types.FOO_WIDGET
    }

但问题是它没有使用项目查询进行计数,它使用两个不同的表来获取所选计数,其中一个表格没有任何过滤。如何让此查询按预期工作?

可运行的示例

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 (?)
'''

要运行此示例,您需要SQLAlchemy(在此处使用SQLA 0.9.7进行测试,在我的实际应用程序中它是0.7.x,两个版本都存在错误)

0 个答案:

没有答案