Многомерные массивы PostgreSQL в SQLAlchemy

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

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

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

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

item_type – тип данных элементов массива. Заметить что размерность здесь не имеет значения, поэтому многомерные массивы, такие как INTEGER [] [], строятся как массив (Integer), а не как 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 ответов


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

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 они упоминают.

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

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


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

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

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

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