Как определить, включен ли один PGArray в другой с помощью сеансов SQLAlchemy?

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

Я хотел бы выбрать любой дочерний node данного node, так что я ищу SQL, который выглядит так (для родителя с pk = 2):

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

Вот код SqlAlchemy/Python, который я использую, чтобы попытаться добраться до вышеупомянутого SQL с небольшой удачей:

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, с которой я заканчиваю (обратите внимание на отсутствие кавычек вокруг имени таблицы treeItems в предложении where):

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 оператор или выражение, которое может делать < @с помощью PGArray?

Как я могу получить кавычки для отображения вокруг имени моей таблицы, если я должен использовать выражение text()?

Спасибо всем!

Теги:
arrays
sqlalchemy

2 ответа

4
Лучший ответ

Элементы предложения SQLAlchemy имеют метод .op() для настраиваемых операторов. То, что недоступно, является специальным предложением для литералов массива. Вы можете указать литерал массива с literal_column:

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

Если вам нужен лучший API для литералов массива, вы можете создать его с помощью модуля sqlalchemy.ext.compiler, добавленного в SQLAlchemy 0.5.4.

0

В этом конкретном случае я заметил, что цитирование в SQL было связано с тем, что я использовал имя таблицы, которое было смешанным. Преобразование имени таблицы из "treeItems" в "tree_items" разрешило проблему с кавычками, и я смог заставить мое текстовое выражение работать:

expr.text('%s <@ %s' % (arrayStr, TreeItem.table.c.lineage))

Это исправление, и хорошо знать, что имена таблиц смешанных событий должны быть указаны, но ответ Ants остается правильным способом решения проблемы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню