From 3268ffae4840738123121234c35bf735dbf84a68 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Tue, 25 Apr 2017 23:29:10 -0700 Subject: [PATCH] Add DistTableCacheEntry->shardValueCompareFunction. That's useful when comparing values a hash-partitioned table is filtered by. The existing shardIntervalCompareFunction is about comparing hashed values, not unhashed ones. The added btree opclass function is so we can get a comparator back. This should be changed much more widely, but is not necessary so far. --- .../distributed/utils/metadata_cache.c | 39 ++++++++++++++++++- src/include/distributed/metadata_cache.h | 10 ++++- .../regress/expected/multi_data_types.out | 12 ++++-- src/test/regress/sql/multi_data_types.sql | 13 +++++-- 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/backend/distributed/utils/metadata_cache.c b/src/backend/distributed/utils/metadata_cache.c index 1b85fa00d..3ee74975c 100644 --- a/src/backend/distributed/utils/metadata_cache.c +++ b/src/backend/distributed/utils/metadata_cache.c @@ -142,6 +142,7 @@ static HeapTuple LookupDistPartitionTuple(Relation pgDistPartition, Oid relation static List * LookupDistShardTuples(Oid relationId); static Oid LookupShardRelation(int64 shardId); static void GetPartitionTypeInputInfo(char *partitionKeyString, char partitionMethod, + Oid *columnTypeId, int32 *columnTypeMod, Oid *intervalTypeId, int32 *intervalTypeMod); static ShardInterval * TupleToShardInterval(HeapTuple heapTuple, TupleDesc tupleDescriptor, Oid intervalTypeId, @@ -603,11 +604,19 @@ BuildCachedShardList(DistTableCacheEntry *cacheEntry) ShardInterval **shardIntervalArray = NULL; ShardInterval **sortedShardIntervalArray = NULL; FmgrInfo *shardIntervalCompareFunction = NULL; + FmgrInfo *shardColumnCompareFunction = NULL; List *distShardTupleList = NIL; int shardIntervalArrayLength = 0; int shardIndex = 0; + Oid columnTypeId = InvalidOid; + int32 columnTypeMod = -1; + Oid intervalTypeId = InvalidOid; + int32 intervalTypeMod = -1; + GetPartitionTypeInputInfo(cacheEntry->partitionKeyString, cacheEntry->partitionMethod, + &columnTypeId, + &columnTypeMod, &intervalTypeId, &intervalTypeMod); @@ -657,7 +666,22 @@ BuildCachedShardList(DistTableCacheEntry *cacheEntry) heap_close(distShardRelation, AccessShareLock); } - /* decide and allocate interval comparison function */ + /* look up value comparison function */ + if (columnTypeId != InvalidOid) + { + /* allocate the comparison function in the cache context */ + MemoryContext oldContext = MemoryContextSwitchTo(CacheMemoryContext); + + shardColumnCompareFunction = GetFunctionInfo(columnTypeId, BTREE_AM_OID, + BTORDER_PROC); + MemoryContextSwitchTo(oldContext); + } + else + { + shardColumnCompareFunction = NULL; + } + + /* look up interval comparison function */ if (intervalTypeId != InvalidOid) { /* allocate the comparison function in the cache context */ @@ -771,6 +795,7 @@ BuildCachedShardList(DistTableCacheEntry *cacheEntry) cacheEntry->shardIntervalArrayLength = shardIntervalArrayLength; cacheEntry->sortedShardIntervalArray = sortedShardIntervalArray; + cacheEntry->shardColumnCompareFunction = shardColumnCompareFunction; cacheEntry->shardIntervalCompareFunction = shardIntervalCompareFunction; } @@ -2068,8 +2093,11 @@ LookupShardRelation(int64 shardId) */ static void GetPartitionTypeInputInfo(char *partitionKeyString, char partitionMethod, + Oid *columnTypeId, int32 *columnTypeMod, Oid *intervalTypeId, int32 *intervalTypeMod) { + *columnTypeId = InvalidOid; + *columnTypeMod = -1; *intervalTypeId = InvalidOid; *intervalTypeMod = -1; @@ -2084,18 +2112,25 @@ GetPartitionTypeInputInfo(char *partitionKeyString, char partitionMethod, *intervalTypeId = partitionColumn->vartype; *intervalTypeMod = partitionColumn->vartypmod; + *columnTypeId = partitionColumn->vartype; + *columnTypeMod = partitionColumn->vartypmod; break; } case DISTRIBUTE_BY_HASH: { + Node *partitionNode = stringToNode(partitionKeyString); + Var *partitionColumn = (Var *) partitionNode; + Assert(IsA(partitionNode, Var)); + *intervalTypeId = INT4OID; + *columnTypeId = partitionColumn->vartype; + *columnTypeMod = partitionColumn->vartypmod; break; } case DISTRIBUTE_BY_NONE: { - *intervalTypeId = InvalidOid; break; } diff --git a/src/include/distributed/metadata_cache.h b/src/include/distributed/metadata_cache.h index 615da7ed3..65f69870a 100644 --- a/src/include/distributed/metadata_cache.h +++ b/src/include/distributed/metadata_cache.h @@ -47,7 +47,15 @@ typedef struct int shardIntervalArrayLength; ShardInterval **sortedShardIntervalArray; - FmgrInfo *shardIntervalCompareFunction; /* NULL if DISTRIBUTE_BY_NONE */ + /* comparator for partition column's type, NULL if DISTRIBUTE_BY_NONE */ + FmgrInfo *shardColumnCompareFunction; + + /* + * Comparator for partition interval type (different from + * shardValueCompareFunction if hash-partitioned), NULL if + * DISTRIBUTE_BY_NONE. + */ + FmgrInfo *shardIntervalCompareFunction; FmgrInfo *hashFunction; /* NULL if table is not distributed by hash */ /* pg_dist_shard_placement metadata */ diff --git a/src/test/regress/expected/multi_data_types.out b/src/test/regress/expected/multi_data_types.out index 2c3de9e53..431c36896 100644 --- a/src/test/regress/expected/multi_data_types.out +++ b/src/test/regress/expected/multi_data_types.out @@ -11,8 +11,13 @@ CREATE TYPE test_composite_type AS ( ); -- ... as well as a function to use as its comparator... CREATE FUNCTION equal_test_composite_type_function(test_composite_type, test_composite_type) RETURNS boolean -AS 'select $1.i = $2.i AND $1.i2 = $2.i2;' -LANGUAGE SQL +LANGUAGE 'internal' +AS 'record_eq' +IMMUTABLE +RETURNS NULL ON NULL INPUT; +CREATE FUNCTION cmp_test_composite_type_function(test_composite_type, test_composite_type) RETURNS int +LANGUAGE 'internal' +AS 'btrecordcmp' IMMUTABLE RETURNS NULL ON NULL INPUT; -- ... use that function to create a custom equality operator... @@ -35,7 +40,8 @@ RETURNS NULL ON NULL INPUT; -- One uses BTREE the other uses HASH CREATE OPERATOR CLASS cats_op_fam_clas3 DEFAULT FOR TYPE test_composite_type USING BTREE AS -OPERATOR 3 = (test_composite_type, test_composite_type); +OPERATOR 3 = (test_composite_type, test_composite_type), +FUNCTION 1 cmp_test_composite_type_function(test_composite_type, test_composite_type); CREATE OPERATOR CLASS cats_op_fam_class DEFAULT FOR TYPE test_composite_type USING HASH AS OPERATOR 1 = (test_composite_type, test_composite_type), diff --git a/src/test/regress/sql/multi_data_types.sql b/src/test/regress/sql/multi_data_types.sql index eaf4c41b4..fdfb1913b 100644 --- a/src/test/regress/sql/multi_data_types.sql +++ b/src/test/regress/sql/multi_data_types.sql @@ -16,8 +16,14 @@ CREATE TYPE test_composite_type AS ( -- ... as well as a function to use as its comparator... CREATE FUNCTION equal_test_composite_type_function(test_composite_type, test_composite_type) RETURNS boolean -AS 'select $1.i = $2.i AND $1.i2 = $2.i2;' -LANGUAGE SQL +LANGUAGE 'internal' +AS 'record_eq' +IMMUTABLE +RETURNS NULL ON NULL INPUT; + +CREATE FUNCTION cmp_test_composite_type_function(test_composite_type, test_composite_type) RETURNS int +LANGUAGE 'internal' +AS 'btrecordcmp' IMMUTABLE RETURNS NULL ON NULL INPUT; @@ -45,7 +51,8 @@ RETURNS NULL ON NULL INPUT; -- One uses BTREE the other uses HASH CREATE OPERATOR CLASS cats_op_fam_clas3 DEFAULT FOR TYPE test_composite_type USING BTREE AS -OPERATOR 3 = (test_composite_type, test_composite_type); +OPERATOR 3 = (test_composite_type, test_composite_type), +FUNCTION 1 cmp_test_composite_type_function(test_composite_type, test_composite_type); CREATE OPERATOR CLASS cats_op_fam_class DEFAULT FOR TYPE test_composite_type USING HASH AS