Составной тип Postgres на Rails 3 - PullRequest
2 голосов
/ 08 сентября 2011

Я обнаружил новую вещь в Postgres: составные типы.Мне очень нравится этот подход, и он будет очень полезен для меня.

Проблема в том, что ActiveRecord в rails не имеет встроенной поддержки для этого.

Вы когда-нибудь использовали составные типы Postgres?с рельсами?Был хороший опыт или вы предпочитаете общий подход к созданию новых моделей для этих вложенных данных?

http://www.postgresql.org/docs/8.4/static/rowtypes.html

Tks!: -)

1 Ответ

4 голосов
/ 08 сентября 2011

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

Несколько вещей приходят на ум со стороны Rails:

  1. ActiveRecord будет сложно форматировать SQL, необходимый для запроса этих объектов. Возможно, вам придется написать собственный SQL, чтобы учесть специальный синтаксис.
  2. ActiveRecord не сможет выполнять неявное приведение пользовательских типов. Это может быть проблематично при попытке доступа к атрибутам через ActiveRecord. Вы можете расширить адаптер PostgreSQL для ActiveRecord, чтобы преобразовывать эти специальные типы данных в пользовательские классы, однако это нетрадиционный подход.

На стороне базы данных приходит на ум несколько вещей:

  1. Из-за того, что эти типы объединяют несколько атрибутов в одну сущность, такой подход может быть сложным для запроса. Это включает в себя указание условий, в которых вам нужно проверить отдельный атрибут для определенного значения. Кроме того, если какой-либо из этих составных типов содержит ключевые ссылки, может быть сложно выполнить параметры CASCADE.
  2. Этот подход к схеме может быть трудным для индексации, если производительность становится проблемой
  3. Этот подход к схеме, похоже, не нормализован так, как должна быть база данных. В предоставленных примерах эти составные данные должны существовать как отдельное определение таблицы со ссылкой на внешний ключ в родительской таблице.

Если конкретное приложение, которое вы имеете в виду, не имеет убедительных преимуществ, я бы предложил более нормализованный подход. Вместо:

CREATE TYPE inventory_item AS (
    name            text,
    supplier_id     integer,
    price           numeric
);

CREATE TABLE on_hand (
    item      inventory_item,
    count     integer
);

INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000);

Вы можете достичь аналогичного результата, выполнив следующее, сохранив полную поддержку ActiveRecord без необходимости расширения адаптера Postgres или создания пользовательских классов:

CREATE TABLE inventory_item (
    id              integer,
    name            text,
    supplier_id     integer,
    price           numeric
);

CREATE TABLE on_hand (
    inventory_item_id     integer,
    count                 integer
);

INSERT INTO inventory_item VALUES ('fuzzy dice', 42, 1.99) RETURNS INTEGER;
INSERT INTO on_hand VALUES (<inventory_item_id>, 1000);
...