Обсуждение: virtual generated column as partition key

Поиск
Список
Период
Сортировка

virtual generated column as partition key

От
jian he
Дата:
hi.

The attached patch is to implement $subject.

demo:
CREATE TABLE t(f1 bigint, f2 bigint GENERATED ALWAYS AS (f1 * 2)
VIRTUAL) PARTITION BY RANGE (f2);

it will works just fine as
CREATE TABLE t(f1 bigint, f2 bigint GENERATED ALWAYS AS (f1 * 2)
VIRTUAL) PARTITION BY RANGE ((f1 *2 );
under the hood.

but the partition key can not be an expression on top of a virtual
generated column.
so the following is not allowed:
CREATE TABLE t(f1 bigint, f2 bigint GENERATED ALWAYS AS (f1 * 2)
VIRTUAL) PARTITION BY RANGE ((f2+1));

The virtual generated column expression for each partition must match with
the partitioned table, since it is used as a partition key. Otherwise, the
partition bound would be dynamically evaluated.
so the following  table gtest_part_key1_0 can not attach to the partition tree.

CREATE TABLE gtest_part_key1 (f1 date, f2 bigint, f3 bigint GENERATED
ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE ((f3)); --ok
CREATE TABLE gtest_part_key1_0(f3 bigint GENERATED ALWAYS AS (f2 * 3)
VIRTUAL, f2 bigint, f1 date);
ALTER TABLE gtest_part_key1 ATTACH PARTITION gtest_part_key1_0 FOR
VALUES FROM (20) TO (30); --error

cross partition update tests added.

A virtual generated column entry in the pg_partitioned_table catalog is marked
as non-zero partattrs and a non-null partexprs, which is abnormal. Normally,
either partattrs is non-zero or partexprs is null.
we should mention this in the doc/src/sgml/catalogs.sgml

Вложения

Re: virtual generated column as partition key

От
jian he
Дата:
hi.

rebased and refactored a lot.

In pg_partitioned_table.partattrs, value 0 indicates that the corresponding
partition key is an expression, non-0 means key is column reference.

For a virtual generated column, partattrs refers to the attribute number of the
virtual generated column, and the corresponding generation expression is stored
in partvirtualexprs. (see below demo).
Because of this, we need to double check all the occurrences of
RelationGetPartitionKey.

CREATE TABLE gtest_part_keyxx  (f2 bigint, f3 bigint GENERATED ALWAYS
AS (f2 * 2) VIRTUAL) PARTITION BY RANGE (f3, f3, f2, f3, (f2+1));
SELECT pg_get_partkeydef('gtest_part_keyxx'::regclass);
         pg_get_partkeydef
------------------------------------
 RANGE (f3, f3, f2, f3, ((f2 + 1)))
(1 row)

SELECT partrelid::regclass, partnatts, partattrs FROM
pg_partitioned_table WHERE partrelid = ('gtest_part_keyxx'::regclass);
    partrelid     | partnatts | partattrs
------------------+-----------+-----------
 gtest_part_keyxx |         5 | 2 2 1 2 0
(1 row)

Вложения