diff options
| -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 |
