pg_pathman icon indicating copy to clipboard operation
pg_pathman copied to clipboard

Не работает регистрация составного ключа

Open Lispython opened this issue 7 years ago • 4 comments

Тестирую возможность расширения для секционирования таблиц.

Создал таблицу следующей структуры:

                                            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:

  1. Создаю свой тип CREATE TYPE partition_key_year_and_month AS (year float8, month float8);
  2. SELECT create_naming_sequence('message');
  3. На выполнение запроса 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.

Lispython avatar Nov 09 '18 15:11 Lispython

Пробовали сделать отдельную функцию которая возвращает этот тип из какой либо даты, и отметить функцию как IMMUTABLE?

ildus avatar Nov 15 '18 09:11 ildus

Добрый день, тот же самый вопрос, только свои функции я создал и отметил их как 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

xo4yecTb avatar Sep 30 '19 11:09 xo4yecTb

Проблема на в пасмане и не в 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 avatar Oct 01 '19 07:10 knizhnik

@knizhnik благодарю за помощь!

xo4yecTb avatar Oct 01 '19 12:10 xo4yecTb