diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/catalog/heap.c | 269 | ||||
| -rw-r--r-- | src/backend/pgxc/locator/locator.c | 4 | ||||
| -rw-r--r-- | src/include/catalog/heap.h | 14 | ||||
| -rw-r--r-- | src/include/pgxc/locator.h | 4 |
4 files changed, 178 insertions, 113 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index ba4d250dbe..18248f4193 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -118,9 +118,6 @@ static Node *cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname); static List *insert_ordered_unique_oid(List *list, Oid datum); -#ifdef PGXC -static Oid *build_subcluster_data(PGXCSubCluster *subcluster, int *numnodes); -#endif /* ---------------------------------------------------------------- @@ -960,6 +957,54 @@ AddRelationDistribution(Oid relid, int numnodes; Oid *nodeoids; + /* Obtain details of distribution information */ + GetRelationDistributionItems(relid, + distributeby, + descriptor, + &locatortype, + &hashalgorithm, + &hashbuckets, + &attnum); + + /* Obtain details of nodes and classify them */ + nodeoids = GetRelationDistributionNodes(subcluster, &numnodes); + + /* Now OK to insert data in catalog */ + PgxcClassCreate(relid, locatortype, attnum, hashalgorithm, + hashbuckets, numnodes, nodeoids); + + /* Make dependency entries */ + myself.classId = PgxcClassRelationId; + myself.objectId = relid; + myself.objectSubId = 0; + + /* Dependency on relation */ + referenced.classId = RelationRelationId; + referenced.objectId = relid; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); +} + +/* + * GetRelationDistributionItems + * Obtain distribution type and related items based on deparsed information + * of clause DISTRIBUTE BY. + * Depending on the column types given a fallback to a safe distribution can be done. + */ +void +GetRelationDistributionItems(Oid relid, + DistributeBy *distributeby, + TupleDesc descriptor, + char *locatortype, + int *hashalgorithm, + int *hashbuckets, + AttrNumber *attnum) +{ + int local_hashalgorithm = 0; + int local_hashbuckets = 0; + char local_locatortype = '\0'; + AttrNumber local_attnum = 0; + if (!distributeby) { /* @@ -970,22 +1015,22 @@ AddRelationDistribution(Oid relid, Form_pg_attribute attr; int i; - locatortype = LOCATOR_TYPE_HASH; + local_locatortype = LOCATOR_TYPE_HASH; for (i = 0; i < descriptor->natts; i++) { attr = descriptor->attrs[i]; - if (IsHashDistributable(attr->atttypid)) + if (IsTypeHashDistributable(attr->atttypid)) { /* distribute on this column */ - attnum = i + 1; + local_attnum = i + 1; break; } } /* If we did not find a usable type, fall back to round robin */ - if (attnum == 0) - locatortype = LOCATOR_TYPE_RROBIN; + if (local_attnum == 0) + local_locatortype = LOCATOR_TYPE_RROBIN; } else { @@ -999,22 +1044,22 @@ AddRelationDistribution(Oid relid, * Validate user-specified hash column. * System columns cannot be used. */ - attnum = get_attnum(relid, distributeby->colname); - if (attnum <= 0 && attnum >= -(int) lengthof(SysAtt)) + local_attnum = get_attnum(relid, distributeby->colname); + if (local_attnum <= 0 && local_attnum >= -(int) lengthof(SysAtt)) { ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("Invalid distribution column specified"))); } - if (!IsHashDistributable(descriptor->attrs[attnum-1]->atttypid)) + if (!IsTypeHashDistributable(descriptor->attrs[local_attnum - 1]->atttypid)) { ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("Column %s is not a hash distributable data type", distributeby->colname))); } - locatortype = LOCATOR_TYPE_HASH; + local_locatortype = LOCATOR_TYPE_HASH; break; case DISTTYPE_MODULO: @@ -1022,30 +1067,30 @@ AddRelationDistribution(Oid relid, * Validate user specified modulo column. * System columns cannot be used. */ - attnum = get_attnum(relid, distributeby->colname); - if (attnum <= 0 && attnum >= -(int) lengthof(SysAtt)) + local_attnum = get_attnum(relid, distributeby->colname); + if (local_attnum <= 0 && local_attnum >= -(int) lengthof(SysAtt)) { ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("Invalid distribution column specified"))); } - if (!IsModuloDistributable(descriptor->attrs[attnum-1]->atttypid)) + if (!IsTypeModuloDistributable(descriptor->attrs[local_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; + local_locatortype = LOCATOR_TYPE_MODULO; break; case DISTTYPE_REPLICATION: - locatortype = LOCATOR_TYPE_REPLICATED; + local_locatortype = LOCATOR_TYPE_REPLICATED; break; case DISTTYPE_ROUNDROBIN: - locatortype = LOCATOR_TYPE_RROBIN; + local_locatortype = LOCATOR_TYPE_RROBIN; break; default: @@ -1055,51 +1100,95 @@ AddRelationDistribution(Oid relid, } } - switch (locatortype) + /* Use default hash values */ + if (local_locatortype == LOCATOR_TYPE_HASH) { - 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; + local_hashalgorithm = 1; + local_hashbuckets = HASH_SIZE; } - /* Check and build list of nodes related to table */ - nodeoids = build_subcluster_data(subcluster, &numnodes); + /* Save results */ + *attnum = local_attnum; + *hashalgorithm = local_hashalgorithm; + *hashbuckets = local_hashbuckets; + *locatortype = local_locatortype; +} - /* - * Sort the list of nodes in ascending order before storing them - * This is required so that indices are stored in ascending order - * and later when node number is found by modulo, it points to the right node - */ - qsort(nodeoids, numnodes, sizeof(Oid), cmp_nodes); - /* Now OK to insert data in catalog */ - PgxcClassCreate(relid, locatortype, attnum, hashalgorithm, - hashbuckets, numnodes, nodeoids); +/* + * BuildRelationDistributionNodes + * Build an unsorted node Oid array based on a node name list. + */ +Oid * +BuildRelationDistributionNodes(List *nodes, int *numnodes) +{ + Oid *nodeoids; + ListCell *item; - /* Make dependency entries */ - myself.classId = PgxcClassRelationId; - myself.objectId = relid; - myself.objectSubId = 0; + *numnodes = 0; - /* Dependency on relation */ - referenced.classId = RelationRelationId; - referenced.objectId = relid; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); + /* Allocate once enough space for OID array */ + nodeoids = (Oid *) palloc0(NumDataNodes * sizeof(Oid)); + + /* Do process for each node name */ + foreach(item, nodes) + { + char *node_name = strVal(lfirst(item)); + Oid noid = get_pgxc_nodeoid(node_name); + + /* Check existence of node */ + if (!OidIsValid(noid)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("PGXC Node %s: object not defined", + node_name))); + + if (get_pgxc_nodetype(noid) != PGXC_NODE_DATANODE) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("PGXC node %s: not a Datanode", + node_name))); + + /* Can be added if necessary */ + if (*numnodes != 0) + { + bool is_listed = false; + int i; + + /* Id Oid already listed? */ + for (i = 0; i < *numnodes; i++) + { + if (nodeoids[i] == noid) + { + is_listed = true; + break; + } + } + + if (!is_listed) + { + (*numnodes)++; + nodeoids[*numnodes - 1] = noid; + } + } + else + { + (*numnodes)++; + nodeoids[*numnodes - 1] = noid; + } + } + + return nodeoids; } + /* - * Build list of node Oids for subcluster. - * In case pgxc_node is empty return an error + * GetRelationDistributionNodes + * Transform subcluster information generated by query deparsing of TO NODE or + * TO GROUP clause into a sorted array of nodes OIDs. */ -static Oid * -build_subcluster_data(PGXCSubCluster *subcluster, int *numnodes) +Oid * +GetRelationDistributionNodes(PGXCSubCluster *subcluster, int *numnodes) { ListCell *lc; Oid *nodes = NULL; @@ -1115,8 +1204,6 @@ build_subcluster_data(PGXCSubCluster *subcluster, int *numnodes) * There could be a difference between the content of pgxc_node catalog * table and current session, because someone may change nodes and not * yet update session data. - * We should use session data because Executor uses it as well to run - * commands on nodes. */ *numnodes = NumDataNodes; @@ -1129,12 +1216,10 @@ build_subcluster_data(PGXCSubCluster *subcluster, int *numnodes) nodes = (Oid *) palloc(NumDataNodes * sizeof(Oid)); for (i = 0; i < NumDataNodes; i++) nodes[i] = PGXCNodeGetNodeOid(i, PGXC_NODE_DATANODE); - - return nodes; } /* Build list of nodes from given group */ - if (subcluster->clustertype == SUBCLUSTER_GROUP) + if (!nodes && subcluster->clustertype == SUBCLUSTER_GROUP) { Assert(list_length(subcluster->members) == 1); @@ -1152,60 +1237,28 @@ build_subcluster_data(PGXCSubCluster *subcluster, int *numnodes) *numnodes = get_pgxc_groupmembers(group_oid, &nodes); } } - else + else if (!nodes) { - /* This is the case of a list of nodes */ - foreach(lc, subcluster->members) - { - char *node_name = strVal(lfirst(lc)); - Oid noid = get_pgxc_nodeoid(node_name); - - /* Check existence of node */ - if (!OidIsValid(noid)) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("PGXC Node %s: object not defined", - node_name))); - - if (get_pgxc_nodetype(noid) != PGXC_NODE_DATANODE) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("PGXC node %s: not a Datanode", - node_name))); - - /* Can be added if necessary */ - if (*numnodes != 0) - { - bool is_listed = false; - int i; - - /* Id Oid already listed? */ - for (i = 0; i < *numnodes; i++) - { - if (nodes[i] == noid) - { - is_listed = true; - break; - } - } - - if (!is_listed) - { - (*numnodes)++; - nodes = (Oid *) repalloc(nodes, *numnodes * sizeof(Oid)); - nodes[*numnodes - 1] = noid; - } - } - else - { - (*numnodes)++; - nodes = (Oid *) palloc(*numnodes * sizeof(Oid)); - nodes[*numnodes - 1] = noid; - } - } + /* + * This is the case of a list of nodes names. + * Here the result is a sorted array of node Oids + */ + nodes = BuildRelationDistributionNodes(subcluster->members, numnodes); } - return nodes; + /* Return a sorted array of node OIDs */ + return SortRelationDistributionNodes(nodes, *numnodes); +} + +/* + * SortRelationDistributionNodes + * Sort elements in a node array. + */ +Oid * +SortRelationDistributionNodes(Oid *nodeoids, int numnodes) +{ + qsort(nodeoids, numnodes, sizeof(Oid), cmp_nodes); + return nodeoids; } #endif diff --git a/src/backend/pgxc/locator/locator.c b/src/backend/pgxc/locator/locator.c index 68174c1298..0652b88725 100644 --- a/src/backend/pgxc/locator/locator.c +++ b/src/backend/pgxc/locator/locator.c @@ -245,7 +245,7 @@ char *pColName; * PGXCTODO - expand support for other data types! */ bool -IsHashDistributable(Oid col_type) +IsTypeHashDistributable(Oid col_type) { if(col_type == INT8OID || col_type == INT2OID @@ -360,7 +360,7 @@ IsDistColumnForRelId(Oid relid, char *part_col_name) * PGXCTODO - expand support for other data types! */ bool -IsModuloDistributable(Oid col_type) +IsTypeModuloDistributable(Oid col_type) { if(col_type == INT8OID || col_type == INT2OID diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 9ead52af49..879e448772 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -124,11 +124,23 @@ extern void CheckAttributeType(const char *attname, bool allow_system_table_mods); #ifdef PGXC -extern void AddRelationDistribution(Oid relid, +/* Functions related to distribution data of relations */ +extern void AddRelationDistribution(Oid relid, DistributeBy *distributeby, PGXCSubCluster *subcluster, List *parentOids, TupleDesc descriptor); +extern void GetRelationDistributionItems(Oid relid, + DistributeBy *distributeby, + TupleDesc descriptor, + char *locatortype, + int *hashalgorithm, + int *hashbuckets, + AttrNumber *attnum); +extern Oid *GetRelationDistributionNodes(PGXCSubCluster *subcluster, + int *numnodes); +extern Oid *BuildRelationDistributionNodes(List *nodes, int *numnodes); +extern Oid *SortRelationDistributionNodes(Oid *nodeoids, int numnodes); #endif #endif /* HEAP_H */ diff --git a/src/include/pgxc/locator.h b/src/include/pgxc/locator.h index 6e4bca32ef..555be50f5f 100644 --- a/src/include/pgxc/locator.h +++ b/src/include/pgxc/locator.h @@ -108,14 +108,14 @@ extern bool IsHashColumn(RelationLocInfo *rel_loc_info, char *part_col_name); extern bool IsHashColumnForRelId(Oid relid, char *part_col_name); extern int GetRoundRobinNode(Oid relid); -extern bool IsHashDistributable(Oid col_type); +extern bool IsTypeHashDistributable(Oid col_type); extern List *GetAllDataNodes(void); extern List *GetAllCoordNodes(void); extern List *GetAnyDataNode(List *relNodes); extern void RelationBuildLocator(Relation rel); extern void FreeRelationLocInfo(RelationLocInfo *relationLocInfo); -extern bool IsModuloDistributable(Oid col_type); +extern bool IsTypeModuloDistributable(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); |
