Многомерные массивы PostgreSQL в SQLAlchemy - PullRequest
8 голосов
/ 16 марта 2012

Я использую SQLAlchemy 0.6.3 с PostgreSQL 8.4 на сжатие Debian. Мне нужна таблица, в которой один столбец хранит что-то в PostgreSQL, которое отображается в Python в виде списка целочисленных списков или кортежей целочисленных кортежей. Э.Г.

((1,2), (3,4), (5,6,7))

В приведенном ниже примере этот столбец model. Я подумал, что разумным подходом может быть сохранение материала в виде таблицы измерений PG 2, которая в PG выглядит как integer[][]. Я не знаю, в какой форме SQLA вернет это в Python, но я надеюсь, что это что-то вроде кортежа кортежей.

Однако я не могу понять, как заставить SQLA дать мне двумерный массив Integer. документация для sqlalchemy.dialects.postgresql.ARRAY говорит

item_type - тип данных элементов этого массива. Обратите внимание, что размерность здесь не имеет значения, поэтому многомерные массивы, такие как INTEGER [] [], создаются как ARRAY (Integer), а не как ARRAY (ARRAY (Целое число)) или что-то подобное. Типовое отображение выясняется на лету.

К сожалению, я понятия не имею, что это значит. Как сопоставление типов может понять это на лету? Нужно создать правильный DDL. Моим первым и единственным предположением о том, как это сделать, было бы ARRAY(ARRAY(Integer)). В настоящее время у меня есть

  crossval_table = Table(
        name, meta,
        Column('id', Integer, primary_key=True),
        Column('created', TIMESTAMP(), default=now()),
        Column('sample', postgresql.ARRAY(Integer)),
        Column('model', postgresql.ARRAY(Integer)),
        Column('time', Float),
        schema = schema,

Это создает следующий DDL

CREATE TABLE crossval (
    id integer NOT NULL,
    created timestamp without time zone,
    sample integer[],
    model integer[],
    "time" double precision
);

что не правильно, конечно. Чего мне не хватает?

Ответы [ 2 ]

4 голосов
/ 21 марта 2012

Я отвечаю на это здесь, поскольку Майк Байер ответил на этот вопрос о пользователях sqlalchemy.

См. ветку о sqlalchemy-user, где Майк Байер отвечает на этот вопрос.Как пояснил Майк, и как я пропустил, читая документацию PG, PG фактически не применяет измерения массива, как и SQLA.Таким образом, можно написать integer[][], но PG не рассматривает это иначе, чем integer[].В частности, и PG, и SQLA будут принимать выражения массива любого измерения.Я не уверен, почему это так.По словам Майка, в документации PG Arrays написано

В текущей реализации также не применяется объявленное количество измерений.Все массивы определенного типа элементов считаются одинаковыми, независимо от размера или количества измерений.Итак, объявление размера массива или количества измерений в CREATE TABLE - это просто документация;это не влияет на поведение во время выполнения.

См. также тикет , который он открыл.Похоже, что это для обеспечения измерения на уровне SQLA.

4 голосов
/ 16 марта 2012

Я пробовал это

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

engine = create_engine('postgresql://:5432/test', echo=True)

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects import postgresql

Base = declarative_base()


from sqlalchemy import Column, Integer, String

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    sample = Column(postgresql.ARRAY(Integer))


Base.metadata.create_all(engine)

Session = sessionmaker(engine)
s = Session()

a = User()
a.name='test'
a.sample = [[1,2], [3,4]]
s.add(a)
s.commit()

Я думаю, что это решит вашу проблему.Потому что в doc они упоминаются.

Однако текущая реализация игнорирует любые предоставленные ограничения размера массива, т. Е. Поведение такое же, как для массивов неопределенной длины.

Так что, если вы ничего не объявляете, то это будет тот массив, который вам нужен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...