From 878357a06082c5ca156edb27212693d8d959d8f1 Mon Sep 17 00:00:00 2001 From: amit Date: Tue, 22 Aug 2017 11:33:27 +0900 Subject: [PATCH 4/5] Some interface changes for partition_bound_{cmp/bsearch} Introduces a notion of PartitionBoundCmpArg, which replaces the set of arguments void *probe and bool probe_is_bound of both partition_bound_cmp and partition_bound_bsearch. It wasn't possible before to specify the number of datums when a non-bound type of probe is passed. Slightly tweaking the existing interface to allow specifying the same seems awkward. So, instead encapsulate that into PartitionBoundCmpArg. Also, modify partition_rbound_datum_cmp to compare caller-specifed number of datums, instead of key->partnatts datums. --- src/backend/catalog/partition.c | 135 ++++++++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 39 deletions(-) diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 8d508e549b..1d6d1d042c 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -207,6 +207,30 @@ typedef struct PartitionSet Bitmapset *other_parts; } PartitionSet; +/* + * PartitionBoundCmpArg - Caller-defined argument to be passed to + * partition_bound_cmp() + * + * The first (fixed) argument involved in a comparison is the partition bound + * found in the catalog, while an instance of the following struct describes + * either a new partition bound being compared against existing bounds + * (is_bound is true in that case and either lbound or rbound is set), or a + * new tuple's partition key specified in datums (where ndatums = number of + * partition key columns specified in the query). + */ +typedef struct PartitionBoundCmpArg +{ + bool is_bound; + union + { + PartitionListValue *lbound; + PartitionRangeBound *rbound; + } bound; + + Datum *datums; + int ndatums; +} PartitionBoundCmpArg; + static int32 qsort_partition_list_value_cmp(const void *a, const void *b, void *arg); static int32 qsort_partition_rbound_cmp(const void *a, const void *b, @@ -235,14 +259,15 @@ static int32 partition_rbound_cmp(PartitionKey key, bool lower1, PartitionRangeBound *b2); static int32 partition_rbound_datum_cmp(PartitionKey key, Datum *rb_datums, PartitionRangeDatumKind *rb_kind, - Datum *tuple_datums); + Datum *tuple_datums, int n_tuple_datums); static int32 partition_bound_cmp(PartitionKey key, PartitionBoundInfo boundinfo, - int offset, void *probe, bool probe_is_bound); + int offset, PartitionBoundCmpArg *arg); static int partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo, - void *probe, bool probe_is_bound, bool *is_equal); + PartitionBoundCmpArg *arg, + bool *is_equal); static void get_partition_dispatch_recurse(Relation rel, Relation parent, List **pds, List **leaf_part_oids); @@ -938,10 +963,16 @@ check_new_partition_bound(char *relname, Relation parent, { int offset; bool equal; - + PartitionListValue lbound; + PartitionBoundCmpArg arg; + + memset(&lbound, 0, sizeof(PartitionListValue)); + lbound.value = val->constvalue; + memset(&arg, 0, sizeof(PartitionBoundCmpArg)); + arg.is_bound = true; + arg.bound.lbound = &lbound; offset = partition_bound_bsearch(key, boundinfo, - &val->constvalue, - true, &equal); + &arg, &equal); if (offset >= 0 && equal) { overlap = true; @@ -992,6 +1023,7 @@ check_new_partition_bound(char *relname, Relation parent, PartitionBoundInfo boundinfo = partdesc->boundinfo; int offset; bool equal; + PartitionBoundCmpArg arg; Assert(boundinfo && boundinfo->strategy == PARTITION_STRATEGY_RANGE && @@ -1013,8 +1045,11 @@ check_new_partition_bound(char *relname, Relation parent, * since the index array is initialised with an extra -1 * at the end. */ - offset = partition_bound_bsearch(key, boundinfo, lower, - true, &equal); + memset(&arg, 0, sizeof(PartitionBoundCmpArg)); + arg.is_bound = true; + arg.bound.rbound = lower; + offset = partition_bound_bsearch(key, boundinfo, &arg, + &equal); if (boundinfo->indexes[offset + 1] < 0) { @@ -1028,9 +1063,9 @@ check_new_partition_bound(char *relname, Relation parent, { int32 cmpval; + arg.bound.rbound = upper; cmpval = partition_bound_cmp(key, boundinfo, - offset + 1, upper, - true); + offset + 1, &arg); if (cmpval < 0) { /* @@ -3475,12 +3510,15 @@ get_partition_for_tuple(PartitionDispatch *pd, { bool equal = false; int cur_offset; + PartitionBoundCmpArg arg; + memset(&arg, 0, sizeof(PartitionBoundCmpArg)); + arg.is_bound = false; + arg.datums = values; + arg.ndatums = key->partnatts; cur_offset = partition_bound_bsearch(key, partdesc->boundinfo, - values, - false, - &equal); + &arg, &equal); if (cur_offset >= 0 && equal) cur_index = partdesc->boundinfo->indexes[cur_offset]; } @@ -3492,6 +3530,7 @@ get_partition_for_tuple(PartitionDispatch *pd, range_partkey_has_null = false; int cur_offset; int i; + PartitionBoundCmpArg arg; /* * No range includes NULL, so this will be accepted by the @@ -3522,12 +3561,13 @@ get_partition_for_tuple(PartitionDispatch *pd, if (range_partkey_has_null) break; + memset(&arg, 0, sizeof(PartitionBoundCmpArg)); + arg.is_bound = false; + arg.datums = values; + arg.ndatums = key->partnatts; cur_offset = partition_bound_bsearch(key, partdesc->boundinfo, - values, - false, - &equal); - + &arg, &equal); /* * The offset returned is such that the bound at * cur_offset is less than or equal to the tuple value, so @@ -3724,12 +3764,12 @@ partition_rbound_cmp(PartitionKey key, static int32 partition_rbound_datum_cmp(PartitionKey key, Datum *rb_datums, PartitionRangeDatumKind *rb_kind, - Datum *tuple_datums) + Datum *tuple_datums, int n_tuple_datums) { int i; int32 cmpval = -1; - for (i = 0; i < key->partnatts; i++) + for (i = 0; i < n_tuple_datums; i++) { if (rb_kind[i] == PARTITION_RANGE_DATUM_MINVALUE) return -1; @@ -3751,11 +3791,11 @@ partition_rbound_datum_cmp(PartitionKey key, * partition_bound_cmp * * Return whether the bound at offset in boundinfo is <, =, or > the argument - * specified in *probe. + * specified in *arg. */ static int32 partition_bound_cmp(PartitionKey key, PartitionBoundInfo boundinfo, - int offset, void *probe, bool probe_is_bound) + int offset, PartitionBoundCmpArg *arg) { Datum *bound_datums = boundinfo->datums[offset]; int32 cmpval = -1; @@ -3763,17 +3803,35 @@ partition_bound_cmp(PartitionKey key, PartitionBoundInfo boundinfo, switch (key->strategy) { case PARTITION_STRATEGY_LIST: - cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0], - key->partcollation[0], - bound_datums[0], - *(Datum *) probe)); - break; + { + Datum listdatum; + + if (arg->is_bound) + listdatum = arg->bound.lbound->value; + else + { + if (arg->ndatums >= 1) + listdatum = arg->datums[0]; + /* + * If no tuple datum to compare with the bound, consider + * the latter to be greater. + */ + else + return 1; + } + + cmpval = DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0], + key->partcollation[0], + bound_datums[0], + listdatum)); + break; + } case PARTITION_STRATEGY_RANGE: { PartitionRangeDatumKind *kind = boundinfo->kind[offset]; - if (probe_is_bound) + if (arg->is_bound) { /* * We need to pass whether the existing bound is a lower @@ -3784,12 +3842,13 @@ partition_bound_cmp(PartitionKey key, PartitionBoundInfo boundinfo, cmpval = partition_rbound_cmp(key, bound_datums, kind, lower, - (PartitionRangeBound *) probe); + arg->bound.rbound); } else cmpval = partition_rbound_datum_cmp(key, bound_datums, kind, - (Datum *) probe); + arg->datums, + arg->ndatums); break; } @@ -3803,20 +3862,19 @@ partition_bound_cmp(PartitionKey key, PartitionBoundInfo boundinfo, /* * Binary search on a collection of partition bounds. Returns greatest - * bound in array boundinfo->datums which is less than or equal to *probe. - * If all bounds in the array are greater than *probe, -1 is returned. + * bound in array boundinfo->datums which is less than or equal to *arg. + * If all bounds in the array are greater than *arg, -1 is returned. * - * *probe could either be a partition bound or a Datum array representing - * the partition key of a tuple being routed; probe_is_bound tells which. - * We pass that down to the comparison function so that it can interpret the - * contents of *probe accordingly. + * *arg could either be a partition bound or a Datum array representing + * the partition key of a tuple being routed. We simply pass that down to + * partition_bound_cmp where it is interpreted appropriately. * * *is_equal is set to whether the bound at the returned index is equal with - * *probe. + * *arg. */ static int partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo, - void *probe, bool probe_is_bound, bool *is_equal) + PartitionBoundCmpArg *arg, bool *is_equal) { int lo, hi, @@ -3829,8 +3887,7 @@ partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo, int32 cmpval; mid = (lo + hi + 1) / 2; - cmpval = partition_bound_cmp(key, boundinfo, mid, probe, - probe_is_bound); + cmpval = partition_bound_cmp(key, boundinfo, mid, arg); if (cmpval <= 0) { lo = mid; -- 2.11.0