1

次のような SqlAlchemy テーブルがあります。

table = sql.Table('treeItems', META,
    sql.Column('id', sql.Integer(), primary_key=True),
    sql.Column('type', sql.String, nullable=False),
    sql.Column('parentId', sql.Integer, sql.ForeignKey('treeItems.id')),
    sql.Column('lineage', PGArray(sql.Integer)),
    sql.Column('depth', sql.Integer),
)

次のようにオブジェクトにマップされます。

orm.mapper(TreeItem, TreeItem.table, polymorphic_on=TreeItem.table.c.type, polymorphic_identity='TreeItem')

特定のノードの任意の子ノードを選択したいので、探しているのは次のような SQL です (pk=2 の親の場合):

SELECT *
FROM "treeItems"
WHERE ARRAY[2] <@ "treeItems".lineage AND "treeItems".id != 2
ORDER BY "treeItems".lineage

上記の SQL にたどり着くために使用する SqlAlchemy/Python コードを次に示します。

arrayStr = 'ARRAY[%s]' % ','.join([str(i) for i in self.lineage])
lineageFilter = expr.text('%s <@ %s' % (arrayStr, TreeItem.table.c.lineage))
query = SESSION.query(TreeItem).filter(expr.and_(lineageFilter, TreeItem.table.c.id!=self.id))

しかし、これが最終的なSQLです(where句のtreeItemsテーブル名を引用符で囲んでいないことに注意してください):

SELECT "treeItems".id AS "treeItems_id", "treeItems".type AS "treeItems_type", "treeItems"."parentId" AS "treeItems_parentId", "treeItems".lineage AS "treeItems_lineage", "treeItems".depth AS "treeItems_depth"
FROM "treeItems"
WHERE ARRAY[2] <@ treeItems.lineage AND "treeItems".id != %(id_1)s

それでは、質問について:

text() 式を使用するよりもこれを行うためのより良い方法はありますか / PGArray で <@ を実行できる SqlAlchemy の演算子または式はありますか?

text() 式を使用する必要がある場合、テーブル名の周りに引用符を表示するにはどうすればよいですか?

みんな、ありがとう!

4

2 に答える 2

4

SQLAlchemy の節要素には、カスタム演算子用の .op() メソッドがあります。利用できないのは、配列リテラルの特別な句です。配列リテラルは、literal_column で指定できます。

print sql.literal_column('ARRAY[2]').op('<@')(table.c.lineage)
# ARRAY[2] <@ "treeItems".lineage

配列リテラル用のより優れた API が必要な場合は、SQLAlchemy 0.5.4 で追加されたsqlalchemy.ext.compilerモジュールを使用して作成できます。

于 2009-06-05T21:53:39.837 に答える