From: Pavan Deolasee Date: Wed, 3 Oct 2018 06:00:30 +0000 (+0530) Subject: Relax restriction for column ordering for partition tables X-Git-Tag: XL_10_R1~20 X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=e6036a5c7debef92ab1fe02f2a9d7f18463913d8;p=postgres-xl.git Relax restriction for column ordering for partition tables We'd put a overly restrictive limitation that the column orders and column positions must match between a partitioned table and it's children. This was done during the PG 10 merge while we were still fixing many other issues. But now is the right time to revisit this restriction. While we still need to ensure that the distribution column's type, name and position matches across all tables, we can relax the restriction for other columns. This should help in a common situation where columns are added and dropped in the parent table. As long as the physical position of the distribution column does not change, one should now be able to create a child table and attach it as a partition without worrying too much about dropped columns. Many other restrictions still apply as they do in PostgreSQL. A few test cases are added to test the new behaviour. --- diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 42e2a5a1d3..f7680f8d38 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -11545,32 +11545,6 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel) errmsg("column \"%s\" in child table must be marked NOT NULL", attributeName))); - /* - * In Postgres-XL, we demand that the attribute positions of the - * child and the parent table must match too. This seems overly - * restrictive and may have other side-effects when one of the - * tables have dropped columns, thus impacting the attribute - * numbering. But having this restriction helps us generate far - * more efficient plans without worrying too much about attribute - * number mismatch. - * - * In common cases of partitioning, the parent table and the - * partition tables will be created at the very beginning and if - * altered, they will be altered together. - * - * Make exception while restoring a schema during node addition. - */ - if (!isRestoreMode && attribute->attnum != childatt->attnum) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("table \"%s\" contains column \"%s\" at " - "position %d, but parent \"%s\" has it at position %d", - RelationGetRelationName(child_rel), - attributeName, childatt->attnum, - RelationGetRelationName(parent_rel), - attribute->attnum), - errhint("Check for column ordering and dropped columns, if any"), - errdetail("Postgres-XL requires attribute positions to match"))); /* * OK, bump the child column's inheritance count. (If we fail * later on, this change will just roll back.) @@ -11825,12 +11799,16 @@ MergeDistributionIntoExisting(Relation child_rel, Relation parent_rel) if (parent_locinfo->partAttrNum != child_locinfo->partAttrNum) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("table \"%s\" is distributed on column \"%s\", but the " - "parent table \"%s\" is distributed on column \"%s\"", + errmsg("table \"%s\" is distributed on column \"%s\" " + "at position %u, but the " + "parent table \"%s\" is distributed on column \"%s\" " + "at position %u", RelationGetRelationName(child_rel), child_locinfo->partAttrName, + parent_locinfo->partAttrNum, RelationGetRelationName(parent_rel), - parent_locinfo->partAttrName), + parent_locinfo->partAttrName, + child_locinfo->partAttrNum), errdetail("Distribution column for the child must be same as the parent"))); /* diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index ef972aad82..b7eec60670 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -772,30 +772,26 @@ update atacc3 set test2 = 4 where test2 is null; alter table atacc3 add constraint foo check (test2>0); -- XXX fails in XL because of column position mismatch alter table atacc3 inherit atacc2; -ERROR: table "atacc3" contains column "test2" at position 5, but parent "atacc2" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any -- fail due to duplicates and circular inheritance alter table atacc3 inherit atacc2; -ERROR: table "atacc3" contains column "test2" at position 5, but parent "atacc2" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: relation "atacc2" would be inherited from more than once alter table atacc2 inherit atacc3; -ERROR: child table is missing column "test" +ERROR: circular inheritance not allowed +DETAIL: "atacc3" is already a child of "atacc2". alter table atacc2 inherit atacc2; ERROR: circular inheritance not allowed DETAIL: "atacc2" is already a child of "atacc2". -- test that we really are a child now (should see 4 not 3 and cascade should go through) --- XXX fails in XL because the previous alter table failed select test2 from atacc2; test2 ------- -(0 rows) + 4 +(1 row) drop table atacc2 cascade; +NOTICE: drop cascades to table atacc3 -- XXX needs a cascade drop in XL because atacc3 is still a child of atacc1 drop table atacc1 cascade; -NOTICE: drop cascades to table atacc3 -- adding only to a parent is allowed as of 9.2 create table atacc1 (test int); create table atacc2 (test2 int) inherits (atacc1); @@ -2154,17 +2150,15 @@ ALTER TABLE test_type_diff ADD COLUMN f2 int; INSERT INTO test_type_diff_c VALUES (1, 2, 3); ALTER TABLE test_type_diff ALTER COLUMN f2 TYPE bigint USING f2::bigint; CREATE TABLE test_type_diff2 (int_two int2, int_four int4, int_eight int8); -CREATE TABLE test_type_diff2_c1 (int_four int4, int_eight int8, int_two int2); +CREATE TABLE test_type_diff2_c1 (int_four int4, int_eight int8, int_two int2) distribute by hash (int_two); CREATE TABLE test_type_diff2_c2 (int_eight int8, int_two int2, int_four int4); CREATE TABLE test_type_diff2_c3 (int_two int2, int_four int4, int_eight int8); ALTER TABLE test_type_diff2_c1 INHERIT test_type_diff2; -ERROR: table "test_type_diff2_c1" contains column "int_two" at position 3, but parent "test_type_diff2" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: table "test_type_diff2_c1" is distributed on column "int_two" at position 1, but the parent table "test_type_diff2" is distributed on column "int_two" at position 3 +DETAIL: Distribution column for the child must be same as the parent ALTER TABLE test_type_diff2_c2 INHERIT test_type_diff2; -ERROR: table "test_type_diff2_c2" contains column "int_two" at position 2, but parent "test_type_diff2" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: table "test_type_diff2_c2" is distributed on column "int_eight", but the parent table "test_type_diff2" is distributed on column "int_two" +DETAIL: Distribution column for the child must be same as the parent ALTER TABLE test_type_diff2_c3 INHERIT test_type_diff2; INSERT INTO test_type_diff2_c1 VALUES (1, 2, 3); INSERT INTO test_type_diff2_c2 VALUES (4, 5, 6); @@ -3360,14 +3354,10 @@ CREATE TABLE fail_part ( a int NOT NULL ); ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1); -ERROR: table "fail_part" contains column "a" at position 2, but parent "list_parted" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: child table "fail_part" has different type for column "b" ALTER TABLE fail_part ALTER b TYPE char (2) COLLATE "POSIX"; ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1); -ERROR: table "fail_part" contains column "a" at position 2, but parent "list_parted" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: child table "fail_part" has different collation for column "b" DROP TABLE fail_part; -- check that the table being attached has all constraints of the parent CREATE TABLE fail_part ( @@ -3375,15 +3365,11 @@ CREATE TABLE fail_part ( a int NOT NULL ); ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1); -ERROR: table "fail_part" contains column "a" at position 2, but parent "list_parted" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: child table is missing constraint "check_a" -- check that the constraint matches in definition with parent's constraint ALTER TABLE fail_part ADD CONSTRAINT check_a CHECK (a >= 0); ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1); -ERROR: table "fail_part" contains column "a" at position 2, but parent "list_parted" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: child table "fail_part" has different definition for check constraint "check_a" DROP TABLE fail_part; -- check the attributes and constraints after partition is attached CREATE TABLE part_1 ( @@ -3677,17 +3663,11 @@ order by attrelid::regclass::text; (3 rows) alter table p1 attach partition p11 for values from (2) to (5); -ERROR: table "p11" contains column "a" at position 4, but parent "p1" has it at position 2 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any insert into p1 (a, b) values (2, 3); -ERROR: no partition of relation "p1" found for row -DETAIL: Partition key of the failing row contains (b) = (3). -- check that partition validation scan correctly detects violating rows alter table p attach partition p1 for values from (1, 2) to (1, 10); -ERROR: table "p1" contains column "a" at position 2, but parent "p" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: table "p1" is distributed on column "b", but the parent table "p" is distributed on column "a" +DETAIL: Distribution column for the child must be same as the parent -- cleanup drop table p; drop table p1; @@ -3713,3 +3693,119 @@ alter table temp_part_parent attach partition temp_part_child for values in (1, 2); -- ok drop table perm_part_parent cascade; drop table temp_part_parent cascade; +-- xl tests +create table xl_parent (a int, b int, c text) partition by list (a); +-- create a partition +create table xl_child1 partition of xl_parent for values in (1, 2, 3); +-- attach a partition +create table xl_child2 (a int, b int, c text); +alter table xl_parent attach partition xl_child2 for values in (4, 5, 6); +-- attach a partition, distribution column position does not match +create table xl_child3 (b int, a int, c text) distribute by hash (a); +alter table xl_parent attach partition xl_child3 for values in (7, 8, 9); +ERROR: table "xl_child3" is distributed on column "a" at position 1, but the parent table "xl_parent" is distributed on column "a" at position 2 +DETAIL: Distribution column for the child must be same as the parent +-- attach a partition, distribution column position matches, others do not +create table xl_child4 (a int, c text, b int) distribute by hash (a); +alter table xl_parent attach partition xl_child4 for values in (10, 11, 12); +create table xl_child5 (a int) distribute by hash (a); +alter table xl_child5 add column c text; +alter table xl_child5 add column b int; +alter table xl_parent attach partition xl_child5 for values in (13, 14, 15); +create table xl_child6 (a int, b int) distribute by hash (b); +alter table xl_child6 distribute by hash (a); +alter table xl_child6 add column c text; +alter table xl_parent attach partition xl_child6 for values in (16, 17, 18); +create table xl_child7 (a int, b int); +alter table xl_child7 drop column b; +alter table xl_child7 add column b int; +alter table xl_child7 add column c text; +alter table xl_parent attach partition xl_child7 for values in (19, 20, 21); +insert into xl_parent values (1, 100, 'us'); +insert into xl_parent values (4, 200, 'they'); +insert into xl_parent values (6, 300, 'me'); +insert into xl_parent values (11, 400, 'mine'); +insert into xl_parent values (12, 500, 'theirs'); +insert into xl_parent values (9, 600, 'ours'); +ERROR: no partition of relation "xl_parent" found for row +DETAIL: Partition key of the failing row contains (a) = (9). +insert into xl_parent values (13, 700, 'yours'); +insert into xl_parent values (16, 800, 'my'); +insert into xl_parent values (19, 900, 'his'); +select * from xl_parent order by a; + a | b | c +----+-----+-------- + 1 | 100 | us + 4 | 200 | they + 6 | 300 | me + 11 | 400 | mine + 12 | 500 | theirs + 13 | 700 | yours + 16 | 800 | my + 19 | 900 | his +(8 rows) + +select * from xl_parent where a = 1; + a | b | c +---+-----+---- + 1 | 100 | us +(1 row) + +select * from xl_parent where a = 10; + a | b | c +---+---+--- +(0 rows) + +select * from xl_parent where a = 4; + a | b | c +---+-----+------ + 4 | 200 | they +(1 row) + +select * from xl_parent where a = 13; + a | b | c +----+-----+------- + 13 | 700 | yours +(1 row) + +drop table xl_parent; +create table xl_parted (a int, b int, c text) partition by list (b) distribute by hash (b); +create table xl_c1 (a int, b int, c text); +alter table xl_parted attach partition xl_c1 for values in (1, 2, 3); +ERROR: table "xl_c1" is distributed on column "a" at position 2, but the parent table "xl_parted" is distributed on column "b" at position 1 +DETAIL: Distribution column for the child must be same as the parent +drop table xl_c1; +create table xl_c1 (a int, b int, c text) distribute by hash (b); +alter table xl_parted attach partition xl_c1 for values in (1, 2, 3); +insert into xl_parted values (100, 1, 'foo'); +insert into xl_parted values (200, 3, 'bar'); +alter table xl_parted drop column a; +create table xl_c2 (b int, c text); +-- fails +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6); +ERROR: table "xl_c2" is distributed on column "b" at position 2, but the parent table "xl_parted" is distributed on column "b" at position 1 +DETAIL: Distribution column for the child must be same as the parent +insert into xl_parted values (5, 'baz'); +ERROR: no partition of relation "xl_parted" found for row +DETAIL: Partition key of the failing row contains (b) = (5). +-- since attach failed above +drop table xl_c2; +create table xl_c2 (a int, b text, c text) distribute by hash (b); +alter table xl_c2 drop column a; +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6); +ERROR: child table "xl_c2" has different type for column "b" +-- since attach failed above +drop table xl_c2; +create table xl_c2 (a int, b int, c text) distribute by hash (b); +alter table xl_c2 drop column a; +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6); +insert into xl_parted values (5, 'baz'); +select * from xl_parted; + b | c +---+----- + 1 | foo + 5 | baz + 3 | bar +(3 rows) + +drop table xl_parted; diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index 8924c86eb1..6e3ec8046a 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -856,3 +856,19 @@ ERROR: cannot create a temporary relation as partition of permanent relation "p create temp table temp_part partition of temp_parted for values in (1, 2); -- ok drop table perm_parted cascade; drop table temp_parted cascade; +-- xl tests +create table xl_parted (a int, b int, c text) partition by list (b) distribute by hash (b); +create table xl_c1 partition of xl_parted for values in (1, 2, 3); +insert into xl_parted values (100, 1, 'foo'); +insert into xl_parted values (200, 3, 'bar'); +alter table xl_parted drop column a; +create table xl_c2 partition of xl_parted for values in (4, 5, 6); +insert into xl_parted values (1, 'foo'); +insert into xl_parted values (3, 'bar'); +insert into xl_parted values (5, 'baz'); +-- syntax error +create table xl_c3 partition of xl_parted for values in (4, 5, 6) distribute by hash (b); +ERROR: syntax error at or near "distribute" +LINE 1: ...c3 partition of xl_parted for values in (4, 5, 6) distribute... + ^ +drop table xl_parted; diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index d2921d6b1b..234f45777a 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -1955,11 +1955,10 @@ create table parent (a text, b int); create table child1 () inherits (parent); -- a child with a different column order -- XXX this fails in XL because we don't allow different column ordering -create table child2 (b int, a text); +create table child2 (b int, a text) distribute by hash(a); alter table child2 inherit parent; -ERROR: table "child2" contains column "a" at position 2, but parent "parent" has it at position 1 -DETAIL: Postgres-XL requires attribute positions to match -HINT: Check for column ordering and dropped columns, if any +ERROR: table "child2" is distributed on column "a" at position 1, but the parent table "parent" is distributed on column "a" at position 2 +DETAIL: Distribution column for the child must be same as the parent -- a child with an extra column create table child3 (c text) inherits (parent); create trigger parent_insert_trig diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index cb7eca0fb2..67ca7f206f 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -578,7 +578,6 @@ alter table atacc3 inherit atacc2; alter table atacc2 inherit atacc3; alter table atacc2 inherit atacc2; -- test that we really are a child now (should see 4 not 3 and cascade should go through) --- XXX fails in XL because the previous alter table failed select test2 from atacc2; drop table atacc2 cascade; -- XXX needs a cascade drop in XL because atacc3 is still a child of atacc1 @@ -1393,7 +1392,7 @@ INSERT INTO test_type_diff_c VALUES (1, 2, 3); ALTER TABLE test_type_diff ALTER COLUMN f2 TYPE bigint USING f2::bigint; CREATE TABLE test_type_diff2 (int_two int2, int_four int4, int_eight int8); -CREATE TABLE test_type_diff2_c1 (int_four int4, int_eight int8, int_two int2); +CREATE TABLE test_type_diff2_c1 (int_four int4, int_eight int8, int_two int2) distribute by hash (int_two); CREATE TABLE test_type_diff2_c2 (int_eight int8, int_two int2, int_four int4); CREATE TABLE test_type_diff2_c3 (int_two int2, int_four int4, int_eight int8); ALTER TABLE test_type_diff2_c1 INHERIT test_type_diff2; @@ -2407,3 +2406,80 @@ alter table temp_part_parent attach partition temp_part_child for values in (1, 2); -- ok drop table perm_part_parent cascade; drop table temp_part_parent cascade; + +-- xl tests +create table xl_parent (a int, b int, c text) partition by list (a); +-- create a partition +create table xl_child1 partition of xl_parent for values in (1, 2, 3); + +-- attach a partition +create table xl_child2 (a int, b int, c text); +alter table xl_parent attach partition xl_child2 for values in (4, 5, 6); + +-- attach a partition, distribution column position does not match +create table xl_child3 (b int, a int, c text) distribute by hash (a); +alter table xl_parent attach partition xl_child3 for values in (7, 8, 9); + +-- attach a partition, distribution column position matches, others do not +create table xl_child4 (a int, c text, b int) distribute by hash (a); +alter table xl_parent attach partition xl_child4 for values in (10, 11, 12); + +create table xl_child5 (a int) distribute by hash (a); +alter table xl_child5 add column c text; +alter table xl_child5 add column b int; +alter table xl_parent attach partition xl_child5 for values in (13, 14, 15); + +create table xl_child6 (a int, b int) distribute by hash (b); +alter table xl_child6 distribute by hash (a); +alter table xl_child6 add column c text; +alter table xl_parent attach partition xl_child6 for values in (16, 17, 18); + +create table xl_child7 (a int, b int); +alter table xl_child7 drop column b; +alter table xl_child7 add column b int; +alter table xl_child7 add column c text; +alter table xl_parent attach partition xl_child7 for values in (19, 20, 21); + +insert into xl_parent values (1, 100, 'us'); +insert into xl_parent values (4, 200, 'they'); +insert into xl_parent values (6, 300, 'me'); +insert into xl_parent values (11, 400, 'mine'); +insert into xl_parent values (12, 500, 'theirs'); +insert into xl_parent values (9, 600, 'ours'); +insert into xl_parent values (13, 700, 'yours'); +insert into xl_parent values (16, 800, 'my'); +insert into xl_parent values (19, 900, 'his'); + +select * from xl_parent order by a; +select * from xl_parent where a = 1; +select * from xl_parent where a = 10; +select * from xl_parent where a = 4; +select * from xl_parent where a = 13; +drop table xl_parent; + +create table xl_parted (a int, b int, c text) partition by list (b) distribute by hash (b); +create table xl_c1 (a int, b int, c text); +alter table xl_parted attach partition xl_c1 for values in (1, 2, 3); +drop table xl_c1; +create table xl_c1 (a int, b int, c text) distribute by hash (b); +alter table xl_parted attach partition xl_c1 for values in (1, 2, 3); +insert into xl_parted values (100, 1, 'foo'); +insert into xl_parted values (200, 3, 'bar'); +alter table xl_parted drop column a; +create table xl_c2 (b int, c text); +-- fails +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6); +insert into xl_parted values (5, 'baz'); +-- since attach failed above +drop table xl_c2; +create table xl_c2 (a int, b text, c text) distribute by hash (b); +alter table xl_c2 drop column a; +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6); +-- since attach failed above +drop table xl_c2; +create table xl_c2 (a int, b int, c text) distribute by hash (b); +alter table xl_c2 drop column a; +alter table xl_parted attach partition xl_c2 for values in (4, 5, 6); +insert into xl_parted values (5, 'baz'); +select * from xl_parted; +drop table xl_parted; diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index 878ee70011..412405c898 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -678,3 +678,17 @@ create temp table temp_part partition of perm_parted for values in (1, 2); -- er create temp table temp_part partition of temp_parted for values in (1, 2); -- ok drop table perm_parted cascade; drop table temp_parted cascade; + +-- xl tests +create table xl_parted (a int, b int, c text) partition by list (b) distribute by hash (b); +create table xl_c1 partition of xl_parted for values in (1, 2, 3); +insert into xl_parted values (100, 1, 'foo'); +insert into xl_parted values (200, 3, 'bar'); +alter table xl_parted drop column a; +create table xl_c2 partition of xl_parted for values in (4, 5, 6); +insert into xl_parted values (1, 'foo'); +insert into xl_parted values (3, 'bar'); +insert into xl_parted values (5, 'baz'); +-- syntax error +create table xl_c3 partition of xl_parted for values in (4, 5, 6) distribute by hash (b); +drop table xl_parted; diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index f6139f0fdd..773bf4f78c 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -1608,7 +1608,7 @@ create table child1 () inherits (parent); -- a child with a different column order -- XXX this fails in XL because we don't allow different column ordering -create table child2 (b int, a text); +create table child2 (b int, a text) distribute by hash(a); alter table child2 inherit parent; -- a child with an extra column