Создайте проверочное ограничение для HSTORE, чтобы поддерживать определенную последовательность данных.

Вопрос касается ограничения проверки поля HSTORE в Postgres.

create table archives_seasonmodel
    (episodes      hstore)

Это очень укороченная версия таблицы, которая у меня есть, но, например, все в порядке.

Эпизоды содержат данные в следующем формате:

{ 
1 => 2020-03-01, 2 => 2020-03-07,  5=> 2020-03-29, 3=> 2020-03-14
}

Где ключ всегда является положительной цифрой, а значение — датой.

Я хочу создать ограничение, которое будет проверять любые новые данные для следующего условия:

– каждая дата в паре ключ/значение должна быть больше или равна предыдущей паре ключ/значение, упорядоченной по ключам ASC.

Хорошие данные:

{ 
1 => 2020-03-01, 2 => 2020-03-07,  5=> 2020-03-29, 3=> 2020-03-14
}
2020-03-29 >= 2020-03-14 >=   2020-03-07 >=  2020-03-01

5 >=3 >=2 >=1

Неверные данные:

{ 
1 => 2020-03-01, 2 => 2020-06-07,  5=> 2020-03-29, 3=> 2020-03-14
}
2020-03-29 >= 2020-03-14 not >=   2020-06-07 >=  2020-03-01

5 >=3 >=2 >=1

2020-03-14 not >= 2020-06-07 но должно быть так как 2020-03-14 имеет ключ 3 2020-06-07 имеет ключ 2. Дата ключа 3 должна быть больше или равна дате ключа 2, потому что 3 > 2.

Возможно ли создать такое ограничение или это просто нереально???

Спасибо


person Aleksei Khatkevich    schedule 11.07.2020    source источник


Ответы (1)


Создайте функцию для проверки условия. Используйте функцию hstore each() и функцию агрегации array_agg().

create or replace function check_episodes(hstore)
returns boolean language sql as $$
    select array_agg(key order by key::int) = array_agg(key order by value::date)
    from each($1)
$$;

create table archives_seasonmodel (
    episodes hstore check (check_episodes(episodes))
);

Db‹›fiddle.

person klin    schedule 11.07.2020
comment
@AlekseiKhatkevich Внимание: ключи и значения являются текстовыми строками в hstore. Левая часть сравнения, возможно, должна быть array_agg(key order by key::int) - person Mike Organek; 11.07.2020
comment
@MikeOrganek - хорошая мысль. Кроме того, второе выражение массива может быть array_agg(key order by value::date) - person klin; 11.07.2020