diff options
author | Pavan Deolasee | 2015-05-21 10:15:59 +0000 |
---|---|---|
committer | Pavan Deolasee | 2015-05-21 10:15:59 +0000 |
commit | 4dec5cbb6aa480d45f771ed35992a1dc1d07a960 (patch) | |
tree | afc2c661ddf320fbffad7f21b61b3ec2bb2f7541 | |
parent | bc4ba671eb6b0bfaf0743764608f725ace8f8319 (diff) |
Add support for materialized views.
Right now we only support MatViews on coordinators. They are not even created
on the datanodes, though when refreshed they will be refreshed on all the
coordinators.
Also extend LOCAL TEMP tables to mean temp tables created only on the
coordinator. This allows us to use the MatView's mechanism of refresh, though
in the longer run we may want to revisit this and see if the refresh mechanism
needs to be dealt differently in XL, especially if we end up supporting
MatViews on the datanodes.
Finally, slightly modify the join push-down so that a table without
distribution mechanism are assumed coordinator only table and joined locally.
This has a side-effect that pg_catalog tables are now also joined on the
coordinator. This needs to be fixed.
-rw-r--r-- | src/backend/commands/matview.c | 44 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 12 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 5 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 5 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 21 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 34 | ||||
-rw-r--r-- | src/backend/postmaster/pgstat.c | 6 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 5 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 87 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 10 | ||||
-rw-r--r-- | src/include/catalog/pg_class.h | 4 | ||||
-rw-r--r-- | src/include/commands/tablecmds.h | 1 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 5 | ||||
-rw-r--r-- | src/include/utils/rel.h | 8 |
14 files changed, 207 insertions, 40 deletions
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index 5130d512a6..0b5053f5f2 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -25,9 +25,15 @@ #include "commands/matview.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" +#ifdef PGXC +#include "commands/vacuum.h" +#endif #include "executor/executor.h" #include "executor/spi.h" #include "miscadmin.h" +#ifdef PGXC +#include "nodes/makefuncs.h" +#endif #include "parser/parse_relation.h" #include "rewrite/rewriteHandler.h" #include "storage/lmgr.h" @@ -554,11 +560,29 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid) if (SPI_connect() != SPI_OK_CONNECT) elog(ERROR, "SPI_connect failed"); +#ifndef PGXC /* Analyze the temp table with the new contents. */ appendStringInfo(&querybuf, "ANALYZE %s", tempname); if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY) elog(ERROR, "SPI_exec failed: %s", querybuf.data); - +#else + { + /* + * Don't want to send down the ANALYZE on the remote nodes because the + * temporary table was not created there to start with. We could have + * invented a special option for ANALYZE to only run locally. But we + * could instead just cook up a VacuumStmt and call vacuum (with + * VACOPT_ANALYZE option of course) directly + */ + VacuumStmt *stmt = makeNode(VacuumStmt); + RangeVar *rv = makeRangeVar( + get_namespace_name(RelationGetNamespace(tempRel)), + RelationGetRelationName(tempRel), -1); + stmt->relation = rv; + stmt->options = VACOPT_ANALYZE; + vacuum(stmt, InvalidOid, true, NULL, false, true); + } +#endif /* * We need to ensure that there are not duplicate rows without NULLs in * the new data set before we can count on the "diff" results. Check for @@ -589,8 +613,22 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid) /* Start building the query for creating the diff table. */ resetStringInfo(&querybuf); + +#ifdef PGXC + /* + * In Postgres-XL we use LOCAL TEMP table to define a table that gets + * created only on the coordinator. In this case, we need the local table + * only + * + * XXX Are we breaking SQL standard compatibility? + */ +#endif appendStringInfo(&querybuf, +#ifdef PGXC + "CREATE LOCAL TEMP TABLE %s AS " +#else "CREATE TEMP TABLE %s AS " +#endif "SELECT mv.ctid AS tid, newdata " "FROM %s mv FULL JOIN %s newdata ON (", diffname, matviewname, tempname); @@ -678,7 +716,11 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid) "ORDER BY tid"); /* Create the temporary "diff" table. */ +#ifdef PGXC + if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT) +#else if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY) +#endif elog(ERROR, "SPI_exec failed: %s", querybuf.data); /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index cf453cae03..0928269cfd 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -11854,6 +11854,18 @@ IsTempTable(Oid relid) return res; } +bool +IsLocalTempTable(Oid relid) +{ + Relation rel; + bool res; + rel = relation_open(relid, NoLock); + res = (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && + rel->rd_locator_info == NULL); + relation_close(rel, NoLock); + return res; +} + /* * IsIndexUsingTemp * diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 75dce487c8..9dfb1f2aa9 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2998,6 +2998,8 @@ CopyCreateStmtFields(const CreateStmt *from, CreateStmt *newnode) COPY_STRING_FIELD(tablespacename); COPY_SCALAR_FIELD(if_not_exists); #ifdef PGXC + COPY_SCALAR_FIELD(islocal); + COPY_SCALAR_FIELD(relkind); COPY_NODE_FIELD(distributeby); COPY_NODE_FIELD(subcluster); #endif @@ -3506,6 +3508,9 @@ _copyCreateTableAsStmt(const CreateTableAsStmt *from) COPY_NODE_FIELD(into); COPY_SCALAR_FIELD(relkind); COPY_SCALAR_FIELD(is_select_into); +#ifdef PGXC + COPY_SCALAR_FIELD(islocal); +#endif return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index fe5ec9aebc..ac82eacbe0 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1129,6 +1129,8 @@ _equalCreateStmt(const CreateStmt *a, const CreateStmt *b) COMPARE_STRING_FIELD(tablespacename); COMPARE_SCALAR_FIELD(if_not_exists); #ifdef PGXC + COMPARE_SCALAR_FIELD(islocal); + COMPARE_SCALAR_FIELD(relkind); COMPARE_NODE_FIELD(distributeby); COMPARE_NODE_FIELD(subcluster); #endif @@ -1553,6 +1555,9 @@ _equalCreateTableAsStmt(const CreateTableAsStmt *a, const CreateTableAsStmt *b) COMPARE_NODE_FIELD(into); COMPARE_SCALAR_FIELD(relkind); COMPARE_SCALAR_FIELD(is_select_into); +#ifdef PGXC + COMPARE_SCALAR_FIELD(islocal); +#endif return true; } diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index ec4bfdb49a..feaed857a9 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -1021,18 +1021,13 @@ set_joinpath_distribution(PlannerInfo *root, JoinPath *pathnode) * Catalog tables are the same on all nodes, so treat them as replicated * on all nodes. */ - if ((!innerd || IsLocatorReplicated(innerd->distributionType)) && - (!outerd || IsLocatorReplicated(outerd->distributionType))) + if ((innerd && IsLocatorReplicated(innerd->distributionType)) && + (outerd && IsLocatorReplicated(outerd->distributionType))) { /* Determine common nodes */ Bitmapset *common; - if (innerd == NULL) - common = bms_copy(outerd->nodes); - else if (outerd == NULL) - common = bms_copy(innerd->nodes); - else - common = bms_intersect(innerd->nodes, outerd->nodes); + common = bms_intersect(innerd->nodes, outerd->nodes); if (bms_is_empty(common)) goto not_allowed_join; @@ -1056,14 +1051,14 @@ set_joinpath_distribution(PlannerInfo *root, JoinPath *pathnode) * nullable data nodes will produce joined rows with NULLs for cases when * matching row exists, but on other data node. */ - if ((!innerd || IsLocatorReplicated(innerd->distributionType)) && + if ((innerd && IsLocatorReplicated(innerd->distributionType)) && (pathnode->jointype == JOIN_INNER || pathnode->jointype == JOIN_LEFT || pathnode->jointype == JOIN_SEMI || pathnode->jointype == JOIN_ANTI)) { /* We need inner relation is defined on all nodes where outer is */ - if (innerd && !bms_is_subset(outerd->nodes, innerd->nodes)) + if (!outerd || !bms_is_subset(outerd->nodes, innerd->nodes)) goto not_allowed_join; targetd = makeNode(Distribution); @@ -1084,12 +1079,12 @@ set_joinpath_distribution(PlannerInfo *root, JoinPath *pathnode) * nullable data nodes will produce joined rows with NULLs for cases when * matching row exists, but on other data node. */ - if ((!outerd || IsLocatorReplicated(outerd->distributionType)) && + if ((outerd && IsLocatorReplicated(outerd->distributionType)) && (pathnode->jointype == JOIN_INNER || pathnode->jointype == JOIN_RIGHT)) { /* We need outer relation is defined on all nodes where inner is */ - if (outerd && !bms_is_subset(innerd->nodes, outerd->nodes)) + if (!innerd || !bms_is_subset(innerd->nodes, outerd->nodes)) goto not_allowed_join; targetd = makeNode(Distribution); @@ -1269,6 +1264,7 @@ not_allowed_join: * by has as main variant. */ +#ifdef NOT_USED /* These join types allow replicated inner */ if (outerd && (pathnode->jointype == JOIN_INNER || @@ -1322,6 +1318,7 @@ not_allowed_join: altpath->path.distribution = targetd; alternate = lappend(alternate, altpath); } +#endif /* * Redistribute subplans to make them compatible. diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 5931e2847e..bbc251fec6 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -2734,6 +2734,12 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $11; n->if_not_exists = false; /* PGXC_BEGIN */ + if ($2 == RELPERSISTENCE_LOCAL_TEMP) + { + $4->relpersistence = RELPERSISTENCE_TEMP; + n->islocal = true; + } + n->relkind = RELKIND_RELATION; n->distributeby = $12; n->subcluster = $13; /* PGXC_END */ @@ -2757,6 +2763,12 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $14; n->if_not_exists = true; /* PGXC_BEGIN */ + if ($2 == RELPERSISTENCE_LOCAL_TEMP) + { + $7->relpersistence = RELPERSISTENCE_TEMP; + n->islocal = true; + } + n->relkind = RELKIND_RELATION; n->distributeby = $15; n->subcluster = $16; if (n->inhRelations != NULL && n->distributeby != NULL) @@ -2785,6 +2797,12 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $10; n->if_not_exists = false; /* PGXC_BEGIN */ + if ($2 == RELPERSISTENCE_LOCAL_TEMP) + { + $4->relpersistence = RELPERSISTENCE_TEMP; + n->islocal = true; + } + n->relkind = RELKIND_RELATION; n->distributeby = $11; n->subcluster = $12; if (n->inhRelations != NULL && n->distributeby != NULL) @@ -2813,6 +2831,12 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $13; n->if_not_exists = true; /* PGXC_BEGIN */ + if ($2 == RELPERSISTENCE_LOCAL_TEMP) + { + $7->relpersistence = RELPERSISTENCE_TEMP; + n->islocal = true; + } + n->relkind = RELKIND_RELATION; n->distributeby = $14; n->subcluster = $15; if (n->inhRelations != NULL && n->distributeby != NULL) @@ -2838,8 +2862,8 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' */ OptTemp: TEMPORARY { $$ = RELPERSISTENCE_TEMP; } | TEMP { $$ = RELPERSISTENCE_TEMP; } - | LOCAL TEMPORARY { $$ = RELPERSISTENCE_TEMP; } - | LOCAL TEMP { $$ = RELPERSISTENCE_TEMP; } + | LOCAL TEMPORARY { $$ = RELPERSISTENCE_LOCAL_TEMP; } + | LOCAL TEMP { $$ = RELPERSISTENCE_LOCAL_TEMP; } | GLOBAL TEMPORARY { ereport(WARNING, @@ -3473,6 +3497,12 @@ CreateAsStmt: ctas->is_select_into = false; /* cram additional flags into the IntoClause */ $4->rel->relpersistence = $2; + if ($2 == RELPERSISTENCE_LOCAL_TEMP) + { + $4->rel->relpersistence = RELPERSISTENCE_TEMP; + ctas->islocal = true; + } + $4->skipData = !($7); $$ = (Node *) ctas; } diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index a05730c769..04a17fda29 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -1892,9 +1892,6 @@ pgstat_update_heap_dead_tuples(Relation rel, int delta) void pgstat_count_remote_insert(Relation rel, int n) { - /* Should be only applied to distributed table */ - Assert(rel->rd_locator_info); - /* For now use the same counters as for heap insert */ pgstat_count_heap_insert(rel, n); } @@ -1908,9 +1905,6 @@ pgstat_count_remote_update(Relation rel, int n) { PgStat_TableStatus *pgstat_info = rel->pgstat_info; - /* Should be only applied to distributed table */ - Assert(rel->rd_locator_info); - if (pgstat_info != NULL) { /* We have to log the effect at the proper transactional level */ diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index c54db93676..be82dedd3e 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -3702,11 +3702,16 @@ QueryRewriteCTAS(Query *parsetree) /* Get the target table */ stmt = (CreateTableAsStmt *) parsetree->utilityStmt; + + if (stmt->relkind == OBJECT_MATVIEW) + return list_make1(parsetree); + relation = stmt->into->rel; /* Start building a CreateStmt for creating the target table */ create_stmt = makeNode(CreateStmt); create_stmt->relation = relation; + create_stmt->islocal = stmt->islocal; into = stmt->into; /* Obtain the target list of new table */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index dff8567bac..77bd7a2a57 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1489,6 +1489,7 @@ ProcessUtilitySlow(Node *parsetree, Oid relOid; #ifdef PGXC bool is_temp = false; + bool is_local = ((CreateStmt *) parsetree)->islocal; #endif /* Run parse analysis ... */ @@ -1501,7 +1502,7 @@ ProcessUtilitySlow(Node *parsetree, * it should explicitly specify distribution. */ stmts = transformCreateStmt((CreateStmt *) parsetree, - queryString, !sentToRemote); + queryString, !is_local && !sentToRemote); #else stmts = transformCreateStmt((CreateStmt *) parsetree, queryString); @@ -1566,7 +1567,9 @@ ProcessUtilitySlow(Node *parsetree, */ if (!sentToRemote) #ifdef XCP - stmts = AddRemoteQueryNode(stmts, queryString, is_temp ? EXEC_ON_DATANODES : EXEC_ON_ALL_NODES); + stmts = AddRemoteQueryNode(stmts, queryString, is_local + ? EXEC_ON_NONE + : (is_temp ? EXEC_ON_DATANODES : EXEC_ON_ALL_NODES)); #else stmts = AddRemoteQueryNode(stmts, queryString, EXEC_ON_ALL_NODES, is_temp); #endif @@ -2133,11 +2136,35 @@ ProcessUtilitySlow(Node *parsetree, case T_CreateTableAsStmt: ExecCreateTableAs((CreateTableAsStmt *) parsetree, queryString, params, completionTag); +#ifdef PGXC + if ((IS_PGXC_COORDINATOR) && !IsConnFromCoord()) + { + CreateTableAsStmt *stmt = (CreateTableAsStmt *) parsetree; + + /* + * CTAS for normal tables should have been rewritten as a + * CREATE TABLE + SELECT INTO + */ + Assert(stmt->relkind == OBJECT_MATVIEW); + if (stmt->into->rel->relpersistence != RELPERSISTENCE_TEMP) + ExecUtilityStmtOnNodes(queryString, NULL, + sentToRemote, false, EXEC_ON_COORDS, false); + } +#endif break; case T_RefreshMatViewStmt: ExecRefreshMatView((RefreshMatViewStmt *) parsetree, queryString, params, completionTag); +#ifdef PGXC + if ((IS_PGXC_COORDINATOR) && !IsConnFromCoord()) + { + RefreshMatViewStmt *stmt = (RefreshMatViewStmt *) parsetree; + if (stmt->relation->relpersistence != RELPERSISTENCE_TEMP) + ExecUtilityStmtOnNodes(queryString, NULL, + sentToRemote, false, EXEC_ON_COORDS, false); + } +#endif break; case T_CreateTrigStmt: @@ -4061,6 +4088,7 @@ ExecUtilityFindNodes(ObjectType object_type, */ case OBJECT_RULE: case OBJECT_VIEW: + case OBJECT_MATVIEW: /* Check if object is a temporary view */ if ((*is_temp = IsTempTable(object_id))) exec_type = EXEC_ON_NONE; @@ -4070,10 +4098,31 @@ ExecUtilityFindNodes(ObjectType object_type, case OBJECT_INDEX: /* Check if given index uses temporary tables */ - if ((*is_temp = IsTempTable(object_id))) - exec_type = EXEC_ON_DATANODES; - else - exec_type = EXEC_ON_ALL_NODES; + { + Relation rel; + bool is_matview; + + rel = relation_open(object_id, NoLock); + + *is_temp = (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP); + is_matview = (rel->rd_rel->relkind == RELKIND_MATVIEW); + + relation_close(rel, NoLock); + + exec_type = EXEC_ON_NONE; + if (*is_temp) + { + if (!is_matview) + exec_type = EXEC_ON_DATANODES; + } + else + { + if (!is_matview) + exec_type = EXEC_ON_ALL_NODES; + else + exec_type = EXEC_ON_COORDS; + } + } break; default: @@ -4107,13 +4156,18 @@ ExecUtilityFindNodesRelkind(Oid relid, bool *is_temp) #endif case RELKIND_RELATION: #ifdef XCP - if ((*is_temp = IsTempTable(relid))) - exec_type = EXEC_ON_DATANODES; - else - exec_type = EXEC_ON_ALL_NODES; + if (*is_temp = IsTempTable(relid)) + { + if (IsLocalTempTable(relid)) + exec_type = EXEC_ON_NONE; + else + exec_type = EXEC_ON_DATANODES; + } + else + exec_type = EXEC_ON_ALL_NODES; #else - *is_temp = IsTempTable(relid); - exec_type = EXEC_ON_ALL_NODES; + *is_temp = IsTempTable(relid); + exec_type = EXEC_ON_ALL_NODES; #endif break; @@ -4124,6 +4178,14 @@ ExecUtilityFindNodesRelkind(Oid relid, bool *is_temp) exec_type = EXEC_ON_COORDS; break; + case RELKIND_MATVIEW: + /* Check if object is a temporary view */ + if ((*is_temp = IsTempTable(relid))) + exec_type = EXEC_ON_NONE; + else + exec_type = EXEC_ON_COORDS; + break; + default: *is_temp = false; exec_type = EXEC_ON_ALL_NODES; @@ -4343,6 +4405,7 @@ DropStmtPreTreatment(DropStmt *stmt, const char *queryString, bool sentToRemote, case OBJECT_SEQUENCE: case OBJECT_VIEW: case OBJECT_INDEX: + case OBJECT_MATVIEW: { /* * Check the list of objects going to be dropped. diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 20e6f80d82..0485ae2383 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -5796,16 +5796,12 @@ get_utility_query_def(Query *query, deparse_context *context) bool istemp = (relation->relpersistence == RELPERSISTENCE_TEMP); bool isunlogged = (relation->relpersistence == RELPERSISTENCE_UNLOGGED); - if (istemp && relation->schemaname) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("temporary tables cannot specify a schema name"))); - - appendStringInfo(buf, "CREATE %s %s TABLE ", + appendStringInfo(buf, "CREATE %s %s %s TABLE ", + stmt->islocal ? "LOCAL" : "", istemp ? "TEMP" : "", isunlogged ? "UNLOGGED" : ""); - if (relation->schemaname && relation->schemaname[0]) + if (!istemp && relation->schemaname && relation->schemaname[0]) appendStringInfo(buf, "%s.", relation->schemaname); appendStringInfo(buf, "%s", relation->relname); diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index f2fb317e5f..b343c4c928 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -161,6 +161,10 @@ DESCR(""); #define RELPERSISTENCE_UNLOGGED 'u' /* unlogged permanent table */ #define RELPERSISTENCE_TEMP 't' /* temporary table */ +#ifdef PGXC +#define RELPERSISTENCE_LOCAL_TEMP 'l' /* local temp table */ +#endif + /* default selection for replica identity (primary key or nothing) */ #define REPLICA_IDENTITY_DEFAULT 'd' /* no replica identity is logged for this relation */ diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 15f487e757..bc97d6ccbe 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -76,6 +76,7 @@ extern void AtEOSubXact_on_commit_actions(bool isCommit, SubTransactionId parentSubid); #ifdef PGXC extern bool IsTempTable(Oid relid); +extern bool IsLocalTempTable(Oid relid); extern bool IsIndexUsingTempTable(Oid relid); extern bool IsOnCommitActions(void); extern void DropTableThrowErrorExternal(RangeVar *relation, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 3aa13d8518..d5a3582399 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1592,6 +1592,8 @@ typedef struct CreateStmt char *tablespacename; /* table space to use, or NULL */ bool if_not_exists; /* just do nothing if it already exists? */ #ifdef PGXC + ObjectType relkind; /* kind of relation to create */ + bool islocal; /* create only on the current node */ DistributeBy *distributeby; /* distribution to use, or NULL */ PGXCSubCluster *subcluster; /* subcluster of table */ #endif @@ -2701,6 +2703,9 @@ typedef struct CreateTableAsStmt Node *query; /* the query (see comments above) */ IntoClause *into; /* destination table */ ObjectType relkind; /* OBJECT_TABLE or OBJECT_MATVIEW */ +#ifdef PGXC + bool islocal; /* local table */ +#endif bool is_select_into; /* it was written as SELECT INTO */ } CreateTableAsStmt; diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 4fd2165db7..2a7c7c6bc4 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -504,6 +504,14 @@ typedef struct StdRdOptions !(relation)->rd_islocaltemp) #endif +#ifdef XCP +/* + * RELATION_IS_COORDINATOR_LOCAL + * Test for a coordinator only relation such as LOCAL TEMP table or a MATVIEW + */ +#define RELATION_IS_COORDINATOR_LOCAL(relation) \ + ((RELATION_IS_LOCAL(relation) && !RelationGetLocInfo(relation))) +#endif /* * RelationIsScannable |