Это интересная особенность PostgreSQL, однако у меня не было возможности поработать с ней.
Несколько вещей приходят на ум со стороны Rails:
- ActiveRecord будет сложно форматировать SQL, необходимый для запроса этих объектов. Возможно, вам придется написать собственный SQL, чтобы учесть специальный синтаксис.
- ActiveRecord не сможет выполнять неявное приведение пользовательских типов. Это может быть проблематично при попытке доступа к атрибутам через ActiveRecord. Вы можете расширить адаптер PostgreSQL для ActiveRecord, чтобы преобразовывать эти специальные типы данных в пользовательские классы, однако это нетрадиционный подход.
На стороне базы данных приходит на ум несколько вещей:
- Из-за того, что эти типы объединяют несколько атрибутов в одну сущность, такой подход может быть сложным для запроса. Это включает в себя указание условий, в которых вам нужно проверить отдельный атрибут для определенного значения. Кроме того, если какой-либо из этих составных типов содержит ключевые ссылки, может быть сложно выполнить параметры CASCADE.
- Этот подход к схеме может быть трудным для индексации, если производительность становится проблемой
- Этот подход к схеме, похоже, не нормализован так, как должна быть база данных. В предоставленных примерах эти составные данные должны существовать как отдельное определение таблицы со ссылкой на внешний ключ в родительской таблице.
Если конкретное приложение, которое вы имеете в виду, не имеет убедительных преимуществ, я бы предложил более нормализованный подход. Вместо:
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);