diff options
| author | Michael P | 2011-02-02 08:12:58 +0000 |
|---|---|---|
| committer | Pavan Deolasee | 2011-05-19 17:49:37 +0000 |
| commit | e08eb37ced7b0d4416a9812432ed365f54aa5a08 (patch) | |
| tree | d4a8cf5552724243b91d4c0b543a3f79ed0eddb2 | |
| parent | 2e81ffec5df4a2a6c1a21973d81d84d7f5b5d6fc (diff) | |
CREATE TABLE: new distribution function MODULO
new catalogue is named pgxc_class.
It has the following columns
pcrelid - The OID of the added relation in pg_class
pclocatortype - XC defines distribution types as a single
character in locator.h
The provided distribution type is stored here.
Distribution types can be
'R' - Replicated
'H' - Based on a column's hash value
'N' - Based on round robin for all data nodes
'M' - Based on modulo of a column's value
This new distribution type is added by this patch.
Similarly G, S and C are also defined.
pcattnum - The number of the column used for replication
valid only for H and M - Zero for the rest
This patch supports also copy and INSERT(SELECT).
It does NOT SUPPPORT multiple INSERT.
The following issues are remaining though:
1) Non-definition of distribution column in table makes a crash
2) Creation of an index on a column that is not the distribution column
3) Creation of a foreign key on distribution column
4) Distribution on another column other than unique makes a crash
| -rw-r--r-- | src/backend/catalog/heap.c | 36 | ||||
| -rw-r--r-- | src/backend/catalog/pgxc_class.c | 2 | ||||
| -rw-r--r-- | src/backend/commands/copy.c | 34 | ||||
| -rw-r--r-- | src/backend/commands/indexcmds.c | 2 | ||||
| -rw-r--r-- | src/backend/parser/gram.y | 20 | ||||
| -rw-r--r-- | src/backend/parser/parse_utilcmd.c | 13 | ||||
| -rw-r--r-- | src/backend/pgxc/locator/locator.c | 148 | ||||
| -rw-r--r-- | src/backend/pgxc/plan/planner.c | 39 | ||||
| -rw-r--r-- | src/include/nodes/primnodes.h | 3 | ||||
| -rw-r--r-- | src/include/parser/kwlist.h | 3 | ||||
| -rw-r--r-- | src/include/pgxc/locator.h | 8 |
11 files changed, 255 insertions, 53 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index a92e73a2b3..ec8d2517c9 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -828,6 +828,7 @@ AddRelationDistribution (Oid relid, switch (locatortype) { case LOCATOR_TYPE_HASH: + case LOCATOR_TYPE_MODULO: attnum = rel_loc_info->partAttrNum; break; @@ -895,6 +896,26 @@ AddRelationDistribution (Oid relid, locatortype = LOCATOR_TYPE_HASH; break; + case DISTTYPE_MODULO: + /* User specified modulo column, validate */ + attnum = get_attnum(relid, distributeby->colname); + if (!attnum) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("Invalid distribution column specified"))); + } + + if (!IsModuloDistributable(descriptor->attrs[attnum-1]->atttypid)) + { + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("Column %s is not modulo distributable data type", + distributeby->colname))); + } + locatortype = LOCATOR_TYPE_MODULO; + break; + case DISTTYPE_REPLICATION: locatortype = LOCATOR_TYPE_REPLICATED; break; @@ -910,12 +931,17 @@ AddRelationDistribution (Oid relid, } } - if (locatortype == LOCATOR_TYPE_HASH) + switch (locatortype) { - /* PGXCTODO */ - /* Use these for now until we make allowing different algorithms more flexible */ - hashalgorithm = 1; - hashbuckets = HASH_SIZE; + case LOCATOR_TYPE_HASH: + /* PGXCTODO */ + /* Use these for now until we make allowing different algorithms more flexible */ + hashalgorithm = 1; + hashbuckets = HASH_SIZE; + break; + + case LOCATOR_TYPE_MODULO: + break; } PgxcClassCreate (relid, locatortype, attnum, hashalgorithm, hashbuckets); diff --git a/src/backend/catalog/pgxc_class.c b/src/backend/catalog/pgxc_class.c index 6b897c8311..08462c2619 100644 --- a/src/backend/catalog/pgxc_class.c +++ b/src/backend/catalog/pgxc_class.c @@ -51,7 +51,7 @@ PgxcClassCreate(Oid pcrelid, values[Anum_pgxc_class_pcrelid - 1] = ObjectIdGetDatum(pcrelid); values[Anum_pgxc_class_pclocatortype - 1] = ObjectIdGetDatum(pclocatortype); - if (pclocatortype == LOCATOR_TYPE_HASH) + if (pclocatortype == LOCATOR_TYPE_HASH || pclocatortype == LOCATOR_TYPE_MODULO) { values[Anum_pgxc_class_pcattnum - 1] = ObjectIdGetDatum(pcattnum); values[Anum_pgxc_class_pchashalgorithm - 1] = ObjectIdGetDatum(pchashalgorithm); diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index b4f19bda29..061d05ed55 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -181,7 +181,7 @@ typedef struct CopyStateData /* Locator information */ RelationLocInfo *rel_loc; /* the locator key */ - int hash_idx; /* index of the hash column */ + int idx_dist_by_col; /* index of the distributed by column */ PGXCNodeHandle **connections; /* Involved data node connections */ TupleDesc tupDesc; /* for INSERT SELECT */ @@ -2312,14 +2312,14 @@ CopyFrom(CopyState cstate) #ifdef PGXC if (IS_PGXC_COORDINATOR && cstate->rel_loc) { - Datum *hash_value = NULL; + Datum *dist_col_value = NULL; - if (cstate->hash_idx >= 0 && !nulls[cstate->hash_idx]) - hash_value = &values[cstate->hash_idx]; + if (cstate->idx_dist_by_col >= 0 && !nulls[cstate->idx_dist_by_col]) + dist_col_value = &values[cstate->idx_dist_by_col]; if (DataNodeCopyIn(cstate->line_buf.data, cstate->line_buf.len, - GetRelationNodes(cstate->rel_loc, (long *)hash_value, + GetRelationNodes(cstate->rel_loc, (long *)dist_col_value, RELATION_ACCESS_INSERT), cstate->connections)) ereport(ERROR, @@ -3737,7 +3737,7 @@ static ExecNodes* build_copy_statement(CopyState cstate, List *attnamelist, TupleDesc tupDesc, bool is_from, List *force_quote, List *force_notnull) { - char *hash_att; + char *pPartByCol; ExecNodes *exec_nodes = makeNode(ExecNodes); @@ -3749,10 +3749,10 @@ build_copy_statement(CopyState cstate, List *attnamelist, */ cstate->rel_loc = GetRelationLocInfo(RelationGetRelid(cstate->rel)); - hash_att = GetRelationHashColumn(cstate->rel_loc); + pPartByCol = GetRelationDistColumn(cstate->rel_loc); if (cstate->rel_loc) { - if (is_from || hash_att) + if (is_from || pPartByCol) exec_nodes->nodelist = list_copy(cstate->rel_loc->nodeList); else { @@ -3764,8 +3764,8 @@ build_copy_statement(CopyState cstate, List *attnamelist, } } - cstate->hash_idx = -1; - if (hash_att) + cstate->idx_dist_by_col = -1; + if (pPartByCol) { List *attnums; ListCell *cur; @@ -3774,9 +3774,9 @@ build_copy_statement(CopyState cstate, List *attnamelist, foreach(cur, attnums) { int attnum = lfirst_int(cur); - if (namestrcmp(&(tupDesc->attrs[attnum - 1]->attname), hash_att) == 0) + if (namestrcmp(&(tupDesc->attrs[attnum - 1]->attname), pPartByCol) == 0) { - cstate->hash_idx = attnum - 1; + cstate->idx_dist_by_col = attnum - 1; break; } } @@ -3903,7 +3903,7 @@ DoInsertSelectCopy(EState *estate, TupleTableSlot *slot) HeapTuple tuple; Datum *values; bool *nulls; - Datum *hash_value = NULL; + Datum *dist_col_value = NULL; MemoryContext oldcontext; CopyState cstate; @@ -4016,14 +4016,14 @@ DoInsertSelectCopy(EState *estate, TupleTableSlot *slot) /* Format the input tuple for sending */ CopyOneRowTo(cstate, 0, values, nulls); - /* Get hash partition column, if any */ - if (cstate->hash_idx >= 0 && !nulls[cstate->hash_idx]) - hash_value = &values[cstate->hash_idx]; + /* Get dist column, if any */ + if (cstate->idx_dist_by_col >= 0 && !nulls[cstate->idx_dist_by_col]) + dist_col_value = &values[cstate->idx_dist_by_col]; /* Send item to the appropriate data node(s) (buffer) */ if (DataNodeCopyIn(cstate->fe_msgbuf->data, cstate->fe_msgbuf->len, - GetRelationNodes(cstate->rel_loc, (long *)hash_value, RELATION_ACCESS_INSERT), + GetRelationNodes(cstate->rel_loc, (long *)dist_col_value, RELATION_ACCESS_INSERT), cstate->connections)) ereport(ERROR, (errcode(ERRCODE_CONNECTION_EXCEPTION), diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 0f1a2e5b63..c25a944f79 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -430,7 +430,7 @@ DefineIndex(RangeVar *heapRelation, if (!isSafe) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("Unique index of partitioned table must contain the hash distribution column."))); + errmsg("Unique index of partitioned table must contain the hash/modulo distribution column."))); } #endif /* diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 11bc8e2643..a4ccc03d3a 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -436,7 +436,7 @@ static TypeName *TableFuncTypeName(List *columns); */ /* ordinary key words in alphabetical order */ -/* PGXC - added REPLICATION, DISTRIBUTE, and HASH */ +/* PGXC - added REPLICATION, DISTRIBUTE, MODULO and HASH */ %token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION @@ -484,9 +484,9 @@ static TypeName *TableFuncTypeName(List *columns); LANCOMPILER LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P LOGIN_P - - MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE - +/* PGXC_BEGIN */ + MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MODULO MONTH_P MOVE +/* PGXC_END */ NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB NOCREATEROLE NOCREATEUSER NODE NOINHERIT NOLOGIN_P NONE NOSUPERUSER NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC @@ -2550,6 +2550,13 @@ OptDistributeBy: DistributeByHash '(' name ')' n->colname = $3; $$ = n; } + | DISTRIBUTE BY MODULO '(' name ')' + { + DistributeBy *n = makeNode(DistributeBy); + n->disttype = DISTTYPE_MODULO; + n->colname = $5; + $$ = n; + } | DISTRIBUTE BY REPLICATION { DistributeBy *n = makeNode(DistributeBy); @@ -10282,7 +10289,7 @@ ColLabel: IDENT { $$ = $1; } /* "Unreserved" keywords --- available for use as any kind of name. */ -/* PGXC - added DISTRIBUTE, HASH, REPLICATION */ +/* PGXC - added DISTRIBUTE, HASH, REPLICATION, MODULO */ unreserved_keyword: ABORT_P | ABSOLUTE_P @@ -10419,6 +10426,9 @@ unreserved_keyword: | MINUTE_P | MINVALUE | MODE +/* PGXC_BEGIN */ + | MODULO +/* PGXC_END */ | MONTH_P | MOVE | NAME_P diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 10e0584852..23e057b0a8 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -2266,7 +2266,7 @@ CheckLocalIndexColumn (char loctype, char *partcolname, char *indexcolname) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("Cannot locally enforce a unique index on round robin distributed table."))); - else if (loctype == LOCATOR_TYPE_HASH) + else if (loctype == LOCATOR_TYPE_HASH || loctype == LOCATOR_TYPE_MODULO) { if (partcolname && indexcolname && strcmp(partcolname, indexcolname) == 0) return true; @@ -2307,12 +2307,13 @@ static checkLocalFKConstraints(CreateStmtContext *cxt) } /* - * See if we are hash partitioned and the column appears in the + * See if we are hash or modulo partitioned and the column appears in the * constraint, and it corresponds to the position in the referenced table. */ if (cxt->isalter) { - if (cxt->rel->rd_locator_info->locatorType == LOCATOR_TYPE_HASH) + if (cxt->rel->rd_locator_info->locatorType == LOCATOR_TYPE_HASH || + cxt->rel->rd_locator_info->locatorType == LOCATOR_TYPE_MODULO) { checkcolname = cxt->rel->rd_locator_info->partAttrName; } @@ -2352,13 +2353,13 @@ static checkLocalFKConstraints(CreateStmtContext *cxt) if (pos >= list_length(fkconstraint->fk_attrs)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("Hash distributed table must include distribution column in index"))); + errmsg("Hash/Modulo distributed table must include distribution column in index"))); /* Verify that the referenced table is partitioned at the same position in the index */ - if (!IsHashColumnForRelId(pk_rel_id, strVal(list_nth(fkconstraint->pk_attrs,pos)))) + if (!IsDistColumnForRelId(pk_rel_id, strVal(list_nth(fkconstraint->pk_attrs,pos)))) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("Hash distribution column does not refer to hash distribution column in referenced table."))); + errmsg("Hash/Modulo distribution column does not refer to hash/modulo distribution column in referenced table."))); } } } diff --git a/src/backend/pgxc/locator/locator.c b/src/backend/pgxc/locator/locator.c index 199293fe41..d1aef8b348 100644 --- a/src/backend/pgxc/locator/locator.c +++ b/src/backend/pgxc/locator/locator.c @@ -158,6 +158,46 @@ get_node_from_hash(int hash) return mappingTable[hash]; } +/* + * compute_modulo + */ +static int +compute_modulo(int valueOfPartCol) +{ + return ((abs(valueOfPartCol)) % NumDataNodes)+1; +} + +/* + * get_node_from_modulo - determine node based on modulo + * + */ +static int +get_node_from_modulo(int modulo) +{ + if (modulo > NumDataNodes || modulo <= 0) + ereport(ERROR, (errmsg("Modulo value out of range\n"))); + + return modulo; +} + +/* + * GetRelationDistColumn - Returns the name of the hash or modulo distribution column + * First hash distribution is checked + * Retuens NULL if the table is neither hash nor modulo distributed + */ +char * +GetRelationDistColumn(RelationLocInfo * rel_loc_info) +{ +char *pColName; + + pColName = NULL; + + pColName = GetRelationHashColumn(rel_loc_info); + if (pColName == NULL) + pColName = GetRelationModuloColumn(rel_loc_info); + + return pColName; +} /* * Returns whether or not the data type is hash distributable with PG-XC @@ -172,9 +212,8 @@ IsHashDistributable(Oid col_type) return false; } - /* - * get_hash_column - return hash column for relation. + * GetRelationHashColumn - return hash column for relation. * * Returns NULL if the relation is not hash partitioned. */ @@ -230,6 +269,95 @@ IsHashColumnForRelId(Oid relid, char *part_col_name) return IsHashColumn(rel_loc_info, part_col_name); } +/* + * IsDistColumnForRelId - return whether or not column for relation is used for hash or modulo distribution + * + */ +bool +IsDistColumnForRelId(Oid relid, char *part_col_name) +{ +bool bRet; +RelationLocInfo *rel_loc_info; + + rel_loc_info = GetRelationLocInfo(relid); + bRet = false; + + bRet = IsHashColumn(rel_loc_info, part_col_name); + if (bRet == false) + IsModuloColumn(rel_loc_info, part_col_name); + return bRet; +} + + +/* + * Returns whether or not the data type is modulo distributable with PG-XC + * PGXCTODO - expand support for other data types! + */ +bool +IsModuloDistributable(Oid col_type) +{ + if (col_type == INT4OID || col_type == INT2OID) + return true; + + return false; +} + +/* + * GetRelationModuloColumn - return modulo column for relation. + * + * Returns NULL if the relation is not modulo partitioned. + */ +char * +GetRelationModuloColumn(RelationLocInfo * rel_loc_info) +{ + char *column_str = NULL; + + if (rel_loc_info == NULL) + column_str = NULL; + else if (rel_loc_info->locatorType != LOCATOR_TYPE_MODULO) + column_str = NULL; + else + { + int len = strlen(rel_loc_info->partAttrName); + + column_str = (char *) palloc(len + 1); + strncpy(column_str, rel_loc_info->partAttrName, len + 1); + } + + return column_str; +} + +/* + * IsModuloColumn - return whether or not column for relation is used for modulo distribution. + * + */ +bool +IsModuloColumn(RelationLocInfo *rel_loc_info, char *part_col_name) +{ + bool ret_value = false; + + if (!rel_loc_info || !part_col_name) + ret_value = false; + else if (rel_loc_info->locatorType != LOCATOR_TYPE_MODULO) + ret_value = false; + else + ret_value = !strcmp(part_col_name, rel_loc_info->partAttrName); + + return ret_value; +} + + +/* + * IsModuloColumnForRelId - return whether or not column for relation is used for modulo distribution. + * + */ +bool +IsModuloColumnForRelId(Oid relid, char *part_col_name) +{ + RelationLocInfo *rel_loc_info = GetRelationLocInfo(relid); + + return IsModuloColumn(rel_loc_info, part_col_name); +} /* * Update the round robin node for the relation @@ -365,6 +493,19 @@ GetRelationNodes(RelationLocInfo *rel_loc_info, long *partValue, exec_nodes->nodelist = list_copy(rel_loc_info->nodeList); break; + case LOCATOR_TYPE_MODULO: + if (partValue != NULL) + /* in prototype, all partitioned tables use same map */ + exec_nodes->nodelist = lappend_int(NULL, get_node_from_modulo(compute_modulo(*partValue))); + else + if (accessType == RELATION_ACCESS_INSERT) + /* Insert NULL to node 1 */ + exec_nodes->nodelist = lappend_int(NULL, 1); + else + /* Use all nodes for other types of access */ + exec_nodes->nodelist = list_copy(rel_loc_info->nodeList); + break; + case LOCATOR_TYPE_SINGLE: /* just return first (there should only be one) */ @@ -420,6 +561,9 @@ ConvertToLocatorType(int disttype) case DISTTYPE_REPLICATION: loctype = LOCATOR_TYPE_REPLICATED; break; + case DISTTYPE_MODULO: + loctype = LOCATOR_TYPE_MODULO; + break; default: ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index c8e67a632a..0c197565d6 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -499,7 +499,8 @@ get_plan_nodes_insert(PlannerInfo *root, RemoteQuery *step) /* Optimization is only done for distributed tables */ if (query->jointree != NULL && query->jointree->fromlist != NULL - && rel_loc_info->locatorType == LOCATOR_TYPE_HASH) + && (rel_loc_info->locatorType == LOCATOR_TYPE_HASH || + rel_loc_info->locatorType == LOCATOR_TYPE_MODULO)) { /* * See if it is "single-step" @@ -526,7 +527,8 @@ get_plan_nodes_insert(PlannerInfo *root, RemoteQuery *step) /* If the source is not hash-based (eg, replicated) also send * through general planner */ - if (step->exec_nodes->baselocatortype != LOCATOR_TYPE_HASH) + if (step->exec_nodes->baselocatortype != LOCATOR_TYPE_HASH && + step->exec_nodes->baselocatortype != LOCATOR_TYPE_MODULO) { step->exec_nodes = NULL; return; @@ -539,8 +541,9 @@ get_plan_nodes_insert(PlannerInfo *root, RemoteQuery *step) } - if (rel_loc_info->locatorType == LOCATOR_TYPE_HASH && - rel_loc_info->partAttrName != NULL) + if ( (rel_loc_info->partAttrName != NULL) && + ( (rel_loc_info->locatorType == LOCATOR_TYPE_HASH) || + (rel_loc_info->locatorType == LOCATOR_TYPE_MODULO) )) { Expr *checkexpr; TargetEntry *tle = NULL; @@ -600,8 +603,9 @@ get_plan_nodes_insert(PlannerInfo *root, RemoteQuery *step) (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), (errmsg("Could not find relation for oid = %d", rte->relid)))); - if (source_rel_loc_info->locatorType == LOCATOR_TYPE_HASH && - strcmp(col_base->colname, source_rel_loc_info->partAttrName) == 0) + if ((strcmp(col_base->colname, source_rel_loc_info->partAttrName) == 0) && + ( (source_rel_loc_info->locatorType == LOCATOR_TYPE_HASH) || + (source_rel_loc_info->locatorType == LOCATOR_TYPE_MODULO) )) { /* * Partition columns match, we have a "single-step INSERT SELECT". @@ -1072,8 +1076,9 @@ examine_conditions_walker(Node *expr_node, XCWalkerContext *context) if (!rel_loc_info1) return true; - /* If hash partitioned, check if the part column was used */ - if (IsHashColumn(rel_loc_info1, column_base->colname)) + /* If hash or modulo partitioned, check if the part column was used */ + if (IsHashColumn(rel_loc_info1, column_base->colname) || + IsModuloColumn(rel_loc_info1, column_base->colname)) { /* add to partitioned literal join conditions */ Literal_Comparison *lit_comp = @@ -1174,8 +1179,10 @@ examine_conditions_walker(Node *expr_node, XCWalkerContext *context) * PGXCTODO - for the prototype, we assume all partitioned * tables are on the same nodes. */ - if (IsHashColumn(rel_loc_info1, column_base->colname) - && IsHashColumn(rel_loc_info2, column_base2->colname)) + if ( ( (IsHashColumn(rel_loc_info1, column_base->colname)) && + (IsHashColumn(rel_loc_info2, column_base2->colname))) || + ( (IsModuloColumn(rel_loc_info1, column_base->colname)) && + (IsModuloColumn(rel_loc_info2, column_base2->colname)))) { /* We found a partitioned join */ Parent_Child_Join *parent_child = (Parent_Child_Join *) @@ -1219,7 +1226,8 @@ examine_conditions_walker(Node *expr_node, XCWalkerContext *context) if (!rel_loc_info1) return true; - if (IsHashColumn(rel_loc_info1, column_base->colname)) + if (IsHashColumn(rel_loc_info1, column_base->colname) || + IsModuloColumn(rel_loc_info1, column_base->colname)) { Expr_Comparison *expr_comp = palloc(sizeof(Expr_Comparison)); @@ -1668,7 +1676,8 @@ get_plan_nodes_walker(Node *query_node, XCWalkerContext *context) if (!rel_loc_info) return true; - if (rel_loc_info->locatorType != LOCATOR_TYPE_HASH) + if (rel_loc_info->locatorType != LOCATOR_TYPE_HASH && + rel_loc_info->locatorType != LOCATOR_TYPE_MODULO) /* do not need to determine partitioning expression */ context->query_step->exec_nodes = GetRelationNodes(rel_loc_info, NULL, @@ -3197,9 +3206,9 @@ validate_part_col_updatable(const Query *query) (errmsg("Could not find relation for oid = %d", rte->relid)))); - /* Only LOCATOR_TYPE_HASH should be checked */ - if (rel_loc_info->locatorType == LOCATOR_TYPE_HASH && - rel_loc_info->partAttrName != NULL) + /* Only LOCATOR_TYPE_HASH & LOCATOR_TYPE_MODULO should be checked */ + if ( (rel_loc_info->partAttrName != NULL) && + ( (rel_loc_info->locatorType == LOCATOR_TYPE_HASH) || (rel_loc_info->locatorType == LOCATOR_TYPE_MODULO) ) ) { /* It is a partitioned table, check partition column in targetList */ foreach(lc, query->targetList) diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 9a96ea6886..c5ca1e5d3c 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -1185,7 +1185,8 @@ typedef enum DistributionType { DISTTYPE_REPLICATION, /* Replicated */ DISTTYPE_HASH, /* Hash partitioned */ - DISTTYPE_ROUNDROBIN /* Round Robin */ + DISTTYPE_ROUNDROBIN, /* Round Robin */ + DISTTYPE_MODULO /* Modulo partitioned */ } DistributionType; /*---------- diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index dc6b96e3b5..d6e0aae515 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -242,6 +242,9 @@ PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD) PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD) PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD) PG_KEYWORD("mode", MODE, UNRESERVED_KEYWORD) +#ifdef PGXC +PG_KEYWORD("modulo", MODULO, UNRESERVED_KEYWORD) +#endif PG_KEYWORD("month", MONTH_P, UNRESERVED_KEYWORD) PG_KEYWORD("move", MOVE, UNRESERVED_KEYWORD) PG_KEYWORD("name", NAME_P, UNRESERVED_KEYWORD) diff --git a/src/include/pgxc/locator.h b/src/include/pgxc/locator.h index 1bc894953f..5948faece6 100644 --- a/src/include/pgxc/locator.h +++ b/src/include/pgxc/locator.h @@ -21,6 +21,7 @@ #define LOCATOR_TYPE_SINGLE 'S' #define LOCATOR_TYPE_RROBIN 'N' #define LOCATOR_TYPE_CUSTOM 'C' +#define LOCATOR_TYPE_MODULO 'M' #define HASH_SIZE 4096 #define HASH_MASK 0x00000FFF; @@ -107,4 +108,11 @@ extern List *GetAnyDataNode(void); extern void RelationBuildLocator(Relation rel); extern void FreeRelationLocInfo(RelationLocInfo *relationLocInfo); +extern bool IsModuloDistributable(Oid col_type); +extern char *GetRelationModuloColumn(RelationLocInfo * rel_loc_info); +extern bool IsModuloColumn(RelationLocInfo *rel_loc_info, char *part_col_name); +extern bool IsModuloColumnForRelId(Oid relid, char *part_col_name); +extern char *GetRelationDistColumn(RelationLocInfo * rel_loc_info); +extern bool IsDistColumnForRelId(Oid relid, char *part_col_name); + #endif /* LOCATOR_H */ |
