1

sqlaclhemy 結合テーブルの継承を使用しようとしたところ、奇妙なことが起こりました。

class CommonObject(Base):
    __tablename__ = "objects"
    id = Column("objid", Integer, primary_key=True)
    objname = Column(String(32))
    ...    

class GoodsPlacement(Container, Loadable, Dumpable):
    __tablename__ = "goods_placements"
    id = Column("objid", Integer, ForeignKey("containers.objid"), primary_key=True)
    ...

class Departure(CommonObject):
     __tablename__ = "departures"
    id = Column(Integer, ForeignKey("objects.objid"),  primary_key=True)
    content_id = Column(Integer, ForeignKey("goods_placements.objid"))
    content = relationship("GoodsPlacement",
        primaryjoin="Departure.content_id==GoodsPlacement.id",
        foreign_keys=[content_id],
        lazy='joined',
        backref="departures")
    ...

クエリを書くとき:

session.query(GoodsPlacement).filter(~GoodsPlacement.departures.any(Departure.status_id < 2))

それは私に次のようなものを生成します:

SELECT 
    objects.objid AS objects_objid,
    goods_placements.objid AS goods_placements_objid,
    objects.objname AS objects_objname 
FROM objects
JOIN goods_placements ON objects.objid = goods_placements.objid 
WHERE NOT (EXISTS (
    SELECT 1 
    FROM (
        SELECT
            objects.objid AS objects_objid,
            objects.objname AS objects_objname,
            departures.id AS departures_id,
            departures.content_id AS departures_content_id,
            departures.status_id AS departures_status_id 
        FROM objects
        JOIN departures ON objects.objid = departures.id)
    AS anon_1, objects 
    WHERE anon_1.departures_content_id = objects.objid
        AND anon_1.departures_status_id < :status_id_1)
)

そして、exist 句のオブジェクトが外部オブジェクトをオーバーライドするため、これは機能しません。私が使用した回避策は sqlexpression から直接存在するため、

session.query(GoodsPlacement).filter(~exists([1],
    and_("departures.status_id<2",
         "departures.content_id=goods_placements.objid"),
    from_obj="departures"))

ただし、列とテーブルの名前に大きく依存します。

existsステートメントでオブジェクトテーブルのエイリアスを指定するにはどうすればよいですか?

Debian wheezy、python-2.7.3rc2、sqlaclhemy 0.7.7-1

4

1 に答える 1

1

列の設定方法に宣言型システムが関与するバグがあります。「id」属性名とは異なる、列に付けている「objid」名が、ここでの問題の原因です。以下のテスト ケースは、上記のシステムに近似しており、バグが修正されるまでの回避策を示しています。

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

Base= declarative_base()

class CommonObject(Base):
    __tablename__ = "objects"
    id = Column("objid", Integer, primary_key=True)
    objname = Column(String(32))

class Container(CommonObject):
    __tablename__ = 'containers'
    id = Column("objid", Integer, ForeignKey("objects.objid"),  primary_key=True)

class GoodsPlacement(Container):
    __tablename__ = "goods_placements"
    id = Column("objid", Integer, ForeignKey("containers.objid"), primary_key=True)


class Departure(CommonObject):
    __tablename__ = "departures"
    id = Column(Integer, ForeignKey("objects.objid"),  primary_key=True)
    content_id = Column(Integer, ForeignKey("goods_placements.objid"))
    status_id = Column(Integer)
    content = relationship("GoodsPlacement",
        primaryjoin=lambda:Departure.__table__.c.content_id==GoodsPlacement.__table__.c.objid,
        backref="departures"
        )

session = Session()
print session.query(GoodsPlacement).filter(~GoodsPlacement.departures.any(Departure.status_id < 2))

出力:

SELECT objects.objid AS objects_objid, containers.objid AS containers_objid, goods_placements.objid AS goods_placements_objid, objects.objname AS objects_objname 
FROM objects JOIN containers ON objects.objid = containers.objid JOIN goods_placements ON containers.objid = goods_placements.objid 
WHERE NOT (EXISTS (SELECT 1 
FROM (SELECT objects.objid AS objects_objid, objects.objname AS objects_objname, departures.id AS departures_id, departures.content_id AS departures_content_id, departures.status_id AS departures_status_id 
FROM objects JOIN departures ON objects.objid = departures.id) AS anon_1 
WHERE anon_1.departures_content_id = goods_placements.objid AND anon_1.departures_status_id < :status_id_1))
于 2012-05-23T16:36:46.497 に答える