Ensure that child table inherits distribution stretegy from the parent.
authorPavan Deolasee <pavan.deolasee@gmail.com>
Thu, 13 Jul 2017 07:24:55 +0000 (12:54 +0530)
committerPavan Deolasee <pavan.deolasee@gmail.com>
Thu, 13 Jul 2017 07:31:20 +0000 (13:01 +0530)
For partitioned tables or in general inherited tables, we now enforce that the
child table always inherit the distribution strategy of the parent. This not
only makes it far easier to handle various cases correctly, but would also
allow us to optimise distributed queries on partitioned tables much easily.

Tank.zhang <6220104@qq.com> originally reported a problem with partitioned
tables and incorrect query execution. Upon investigations, we decided to make
these restrictions to simplify things.

src/backend/parser/parse_utilcmd.c
src/test/regress/expected/alter_table.out
src/test/regress/expected/foreign_key.out
src/test/regress/expected/inherit.out
src/test/regress/expected/updatable_views.out
src/test/regress/expected/with.out
src/test/regress/expected/xc_for_update.out
src/test/regress/expected/xc_prepared_xacts.out

index 1cdeacf3b51d3443e53cfbe191e234be3fb4aec1..67658db41d1e8ee0a190668f293e9bd9a8a6f89d 100644 (file)
@@ -360,6 +360,72 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
                                                                                  (Node *) makeInteger(true), -1),
                                                          stmt->options);
 
+       /*
+        * If the table is inherited then use the distribution strategy of the
+        * parent. We must have already checked for multiple parents and raised an
+        * ERROR since Postgres-XL does not support inheriting from multiple
+        * parents.
+        */
+       if (stmt->inhRelations && IS_PGXC_COORDINATOR && autodistribute)
+       {
+               RangeVar   *inh = (RangeVar *) linitial(stmt->inhRelations);
+               Relation        rel;
+
+               Assert(IsA(inh, RangeVar));
+               rel = heap_openrv(inh, AccessShareLock);
+               if ((rel->rd_rel->relkind != RELKIND_RELATION) &&
+                       (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE))
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                                        errmsg("inherited relation \"%s\" is not a table",
+                                                       inh->relname)));
+
+               if (stmt->distributeby)
+               {
+                       if (!rel->rd_locator_info)
+                               ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                        errmsg("parent table \"%s\" is not distributed, but "
+                                                "distribution is specified for the child table \"%s\"",
+                                                RelationGetRelationName(rel),
+                                                stmt->relation->relname)));
+                       ereport(WARNING,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("Inherited/partition tables inherit"
+                                        " distribution from the parent"),
+                                errdetail("Explicitly specified distribution will be ignored")));
+               }
+               else
+                       stmt->distributeby = makeNode(DistributeBy);
+
+
+               if (rel->rd_locator_info)
+               {
+                       switch (rel->rd_locator_info->locatorType)
+                       {
+                               case LOCATOR_TYPE_HASH:
+                                       stmt->distributeby->disttype = DISTTYPE_HASH;
+                                       stmt->distributeby->colname =
+                                                       pstrdup(rel->rd_locator_info->partAttrName);
+                                       break;
+                               case LOCATOR_TYPE_MODULO:
+                                       stmt->distributeby->disttype = DISTTYPE_MODULO;
+                                       stmt->distributeby->colname =
+                                                       pstrdup(rel->rd_locator_info->partAttrName);
+                                       break;
+                               case LOCATOR_TYPE_REPLICATED:
+                                       stmt->distributeby->disttype = DISTTYPE_REPLICATION;
+                                       break;
+                               case LOCATOR_TYPE_RROBIN:
+                               default:
+                                       stmt->distributeby->disttype = DISTTYPE_ROUNDROBIN;
+                                       break;
+                       }
+                       stmt->subcluster = makeSubCluster(rel->rd_locator_info->rl_nodeList);
+               }
+               heap_close(rel, NoLock);
+       }
+
        /*
         * transformIndexConstraints wants cxt.alist to contain only index
         * statements, so transfer anything we already have into save_alist.
@@ -417,53 +483,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
                        stmt->distributeby->disttype = DISTTYPE_REPLICATION;
                        stmt->distributeby->colname = NULL;
                }
-               /*
-                * If there are parent tables ingerit distribution of the first parent
-                */
-               else if (cxt.fallback_source < FBS_UIDX && stmt->inhRelations)
-               {
-                       RangeVar   *inh = (RangeVar *) linitial(stmt->inhRelations);
-                       Relation        rel;
-
-                       Assert(IsA(inh, RangeVar));
-                       rel = heap_openrv(inh, AccessShareLock);
-                       if ((rel->rd_rel->relkind != RELKIND_RELATION) &&
-                               (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE))
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                                errmsg("inherited relation \"%s\" is not a table",
-                                                               inh->relname)));
-
-                       if (rel->rd_locator_info)
-                       {
-                               switch (rel->rd_locator_info->locatorType)
-                               {
-                                       case LOCATOR_TYPE_HASH:
-                                               stmt->distributeby->disttype = DISTTYPE_HASH;
-                                               stmt->distributeby->colname =
-                                                               pstrdup(rel->rd_locator_info->partAttrName);
-                                               break;
-                                       case LOCATOR_TYPE_MODULO:
-                                               stmt->distributeby->disttype = DISTTYPE_MODULO;
-                                               stmt->distributeby->colname =
-                                                               pstrdup(rel->rd_locator_info->partAttrName);
-                                               break;
-                                       case LOCATOR_TYPE_REPLICATED:
-                                               stmt->distributeby->disttype = DISTTYPE_REPLICATION;
-                                               break;
-                                       case LOCATOR_TYPE_RROBIN:
-                                       default:
-                                               stmt->distributeby->disttype = DISTTYPE_ROUNDROBIN;
-                                               break;
-                               }
-                               /*
-                                * Use defined node, if nothing defined get from the parent
-                                */
-                               if (stmt->subcluster == NULL)
-                                       stmt->subcluster = makeSubCluster(rel->rd_locator_info->rl_nodeList);
-                       }
-                       heap_close(rel, NoLock);
-               }
                /*
                 * If there are columns suitable for hash distribution distribute on
                 * first of them.
index a2937251d5e848a216f4a6f50136a32b01273d30..866dc3f5bf1d63c475fcd7657e5eee0eb459e960 100644 (file)
@@ -1462,6 +1462,8 @@ drop table test;
 -- test inheritance
 create table dropColumn (a int, b int, e int) distribute by replication;
 create table dropColumnChild (c int) inherits (dropColumn) distribute by replication;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 create table dropColumnAnother (d int) inherits (dropColumnChild);
 -- these two should fail
 alter table dropColumnchild drop column a;
@@ -1498,6 +1500,8 @@ ERROR:  column must be added to child tables too
 -- Test corner cases in dropping of inherited columns
 create table p1 (f1 int, f2 int) distribute by roundrobin;
 create table c1 (f1 int not null) inherits(p1) distribute by roundrobin;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 NOTICE:  merging column "f1" with inherited definition
 -- should be rejected since c1.f1 is inherited
 alter table c1 drop column f1;
@@ -1520,6 +1524,8 @@ drop table p1 cascade;
 NOTICE:  drop cascades to table c1
 create table p1 (f1 int, f2 int) distribute by roundrobin;
 create table c1 () inherits(p1) distribute by roundrobin;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 -- should be rejected since c1.f1 is inherited
 alter table c1 drop column f1;
 ERROR:  cannot drop inherited column "f1"
@@ -1534,6 +1540,8 @@ drop table p1 cascade;
 NOTICE:  drop cascades to table c1
 create table p1 (f1 int, f2 int) distribute by roundrobin;
 create table c1 () inherits(p1) distribute by roundrobin;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 -- should be rejected since c1.f1 is inherited
 alter table c1 drop column f1;
 ERROR:  cannot drop inherited column "f1"
@@ -1544,6 +1552,8 @@ drop table p1 cascade;
 NOTICE:  drop cascades to table c1
 create table p1 (f1 int, f2 int) distribute by roundrobin;
 create table c1 (f1 int not null) inherits(p1) distribute by roundrobin;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 NOTICE:  merging column "f1" with inherited definition
 -- should be rejected since c1.f1 is inherited
 alter table c1 drop column f1;
index 0559b0380b0270c2e6a05ffc6e180373d87300e8..8e91bb7a8756d773a3ca8cc09b372e73b041f4e0 100644 (file)
@@ -841,6 +841,8 @@ DETAIL:  Key columns "ptest4" and "ptest1" are of incompatible types: inet and i
 -- Basic 2 table case: 1 column of matching types.
 create table pktable_base (base1 int not null) DISTRIBUTE BY REPLICATION;
 create table pktable (ptest1 int, primary key(base1), unique(base1, ptest1)) inherits (pktable_base) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 create table fktable (ftest1 int references pktable(base1));
 -- now some ins, upd, del
 insert into pktable(base1) values (1);
@@ -901,6 +903,8 @@ drop table pktable_base;
 create table pktable_base(base1 int not null, base2 int) DISTRIBUTE BY REPLICATION;
 create table pktable(ptest1 int, ptest2 int, primary key(base1, ptest1), foreign key(base2, ptest2) references
                                              pktable(base1, ptest1)) inherits (pktable_base) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 insert into pktable (base1, ptest1, base2, ptest2) values (1, 1, 1, 1);
 insert into pktable (base1, ptest1, base2, ptest2) values (2, 1, 1, 1);
 insert into pktable (base1, ptest1, base2, ptest2) values (2, 2, 2, 1);
index b30b38a98628d06e0ac2dafaf2f66a0ddbb8b39f..c5415a63310a003937141560ea25d4f4e32dfa3f 100644 (file)
@@ -3,8 +3,14 @@
 --
 CREATE TABLE a (aa TEXT) distribute by roundrobin;
 CREATE TABLE b (bb TEXT) INHERITS (a) distribute by roundrobin;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 CREATE TABLE c (cc TEXT) INHERITS (a) distribute by roundrobin;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 CREATE TABLE d (dd TEXT) INHERITS (b,c,a) distribute by roundrobin;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 NOTICE:  merging multiple inherited definitions of column "aa"
 NOTICE:  merging multiple inherited definitions of column "aa"
 INSERT INTO a(aa) VALUES('aaa');
index e9758b0b4147abd0abb42f827c5ff81d77a0e0b5..1a05e62f3d6873a77ae0a4151a1264eb52c93926 100644 (file)
@@ -1313,6 +1313,8 @@ drop cascades to view rw_view3
 -- inheritance tests
 CREATE TABLE base_tbl_parent (a int) DISTRIBUTE BY REPLICATION;
 CREATE TABLE base_tbl_child (CHECK (a > 0)) INHERITS (base_tbl_parent) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 INSERT INTO base_tbl_parent SELECT * FROM generate_series(-8, -1);
 INSERT INTO base_tbl_child SELECT * FROM generate_series(1, 8);
 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl_parent;
@@ -2032,16 +2034,22 @@ INSERT INTO t1
 SELECT i,i,'t1' FROM generate_series(1,10) g(i);
 ANALYZE t1;
 CREATE TABLE t11 (d text) INHERITS (t1) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 CREATE INDEX t11_a_idx ON t11(a);
 INSERT INTO t11
 SELECT i,i,'t11','t11d' FROM generate_series(1,10) g(i);
 ANALYZE t11;
 CREATE TABLE t12 (e int[]) INHERITS (t1) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 CREATE INDEX t12_a_idx ON t12(a);
 INSERT INTO t12
 SELECT i,i,'t12','{1,2}'::int[] FROM generate_series(1,10) g(i);
 ANALYZE t12;
 CREATE TABLE t111 () INHERITS (t11, t12) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 NOTICE:  merging multiple inherited definitions of column "a"
 NOTICE:  merging multiple inherited definitions of column "b"
 NOTICE:  merging multiple inherited definitions of column "c"
index 8ff98d620469dd84a630dd4cb9bf98bf6006d930..03dfd56aacb2f9f6256615f008880a42bf39ee83 100644 (file)
@@ -1709,7 +1709,11 @@ DROP FUNCTION y_trigger();
 -- WITH attached to inherited UPDATE or DELETE
 CREATE TEMP TABLE parent ( id int, val text ) DISTRIBUTE BY REPLICATION;
 CREATE TEMP TABLE child1 ( ) INHERITS ( parent ) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 CREATE TEMP TABLE child2 ( ) INHERITS ( parent ) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 INSERT INTO parent VALUES ( 1, 'p1' );
 INSERT INTO child1 VALUES ( 11, 'c11' ),( 12, 'c12' );
 INSERT INTO child2 VALUES ( 23, 'c21' ),( 24, 'c22' );
index 30a2f073218dd0ba43dc1e83e811d4aa499cbe28..e74d015b02575b7a56530e20bc9a8b581bdd063d 100644 (file)
@@ -946,6 +946,8 @@ create table t2(val int, val2 int) DISTRIBUTE BY REPLICATION;
 create table t3(val int, val2 int) DISTRIBUTE BY REPLICATION;
 create table p1(a int, b int) DISTRIBUTE BY REPLICATION;
 create table c1(d int, e int) inherits (p1) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 -- insert some rows in them
 insert into t1 values(1,11),(2,11);
 insert into t2 values(3,11),(4,11);
index 889a8495d7efe39f000cd86120cd01ccbf9bf409..d4b1caae6f110bf87abfd1316b15595d163b0872 100644 (file)
@@ -9,6 +9,8 @@ create table t2(val int, val2 int) DISTRIBUTE BY REPLICATION;
 create table t3(val int, val2 int) DISTRIBUTE BY REPLICATION;
 create table p1(a int, b int) DISTRIBUTE BY REPLICATION;
 create table c1(d int, e int) inherits (p1) DISTRIBUTE BY REPLICATION;
+WARNING:  Inherited/partition tables inherit distribution from the parent
+DETAIL:  Explicitly specified distribution will be ignored
 -- insert some rows in them
 insert into t1 values(1,11),(2,11);
 insert into t2 values(3,11),(4,11);