pg_pathman
pg_pathman copied to clipboard
Не работает регистрация составного ключа
Тестирую возможность расширения для секционирования таблиц.
Создал таблицу следующей структуры:
Table "public.message"
Column | Type | Collation | Nullable | Default
-----------------------+--------------------------+-----------+----------+-------------------------------------------------
id | integer | | not null | nextval('message_id_seq'::regclass)
created_at | timestamp with time zone | | not null | now()
status | integer | | |
transaction_id | character varying(124) | | not null |
Indexes:
"message_pkey" PRIMARY KEY, btree (id)
"message_transaction_id__pkey" UNIQUE CONSTRAINT, btree (transaction_id)
"message_created_at__idx" btree (created_at)
Хочу секционировать таблицу по месяцам с использованием составного ключа по документации https://postgrespro.ru/docs/postgrespro/10/pg-pathman#PG-PATHMAN-INTERNALS:
- Создаю свой тип
CREATE TYPE partition_key_year_and_month AS (year float8, month float8); SELECT create_naming_sequence('message');- На выполнение запроса
SELECT add_to_pathman_config('message', '(extract(year from created_at), extract(month from created_at))::partition_key_year_and_month', NULL);вылетает следующая ошибка:
ERROR: failed to analyze partitioning expression "(extract(year from created_at), extract(month from created_at))::partition_key_year_and_month"
DETAIL: functions in partitioning expression must be marked IMMUTABLE
Environment
extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition
------------+----------+--------------+----------------+------------+---------------+--------------
plpgsql | 10 | 11 | f | 1.0 | |
pg_pathman | 10 | 2200 | f | 1.5 | {16387,16398} | {"",""}
version
----------------------------------------------------------------------------------------------------------------------------------
PostgreSQL 11.0 (Debian 11.0-1.pgdg90+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit
(1 row)
ERROR: function get_pathman_lib_version() does not exist
LINE 1: SELECT get_pathman_lib_version();
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Пробовали сделать отдельную функцию которая возвращает этот тип из какой либо даты, и отметить функцию как IMMUTABLE?
Добрый день, тот же самый вопрос, только свои функции я создал и отметил их как IMMUTABLE:
CREATE FUNCTION extract_month(timestamp) RETURNS double precision
AS $BODY$ select extract(month from $1) $BODY$
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
CREATE FUNCTION extract_year(timestamp) RETURNS double precision
AS $BODY$ select extract(year from $1) $BODY$
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
затем
select add_to_pathman_config('table','(extract_year(created_at::timestamp),extract_month(created_at::timestamp))::outcomes_key',NULL);
ОШИБКА: failed to analyze partitioning expression "(extract_year(created_at::timestamp),extract_month(created_at::timestamp))::outcomes_key"
ПОДРОБНОСТИ: functions in partitioning expression must be marked IMMUTABLE
Что здесь не так? @ildus
Проблема на в пасмане и не в extract, а в with time zone. Если вы попробуете создать функциональный индекс, то получите такую же ошибку:
create table tt(t timestamp with time zone); create index tti on tt (extract(year from t)); ERROR: functions in index expression must be marked IMMUTABLE
Если же вы не используете with time zone, то всё будет нормально:
create table tt(t timestamp); create index tti on tt (extract(year from t));
В вашем случае объявление immutable функций не решало проблему, потому как параметр функции был объявлен как timestamp и поэтому всё равно происходило преробразование timestamp with timezone в timestamp, которое не immutable.
Проблему можно решить объявив параметр функиии как timestamp with timezone:
CREATE FUNCTION extract_month(timestamp with time zone) RETURNS double precision AS $BODY$ select extract(month from $1) $BODY$ LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT;
create table tt(t timestamp with time zone); create index tti on tt (extract_month(t)); CREATE INDEX
@knizhnik благодарю за помощь!