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

StackOverflow https://stackoverflow.com/questions/957762

Вопрос

У меня есть таблица 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

Вот код 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()?

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top