我有一个像这样的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()表达式更好的方法/在SqlAlchemy中是否有一个运算符或表达式可以&lt; @ with PGArray?
如果我必须使用text()表达式,如何在表名周围显示引号?
谢谢大家!
答案 0 :(得分: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模块创建它。
答案 1 :(得分:0)
在这个特殊情况下,我注意到SQL中的引用是由于我使用的是混合大小写的表名。将表名从'treeItems'转换为'tree_items'解决了引用问题,我能够使我的文本表达式起作用:
expr.text('%s <@ %s' % (arrayStr, TreeItem.table.c.lineage))
这是一个修复,很高兴知道需要引用混合案例表名称,但蚂蚁的回答仍然是解决问题的正确方法。