0002-WIP-Interface-changes-for-partition_bound_-cmp-bsear.patch

text/plain

Filename: 0002-WIP-Interface-changes-for-partition_bound_-cmp-bsear.patch
Type: text/plain
Part: 1
Message: Re: path toward faster partition pruning

Patch

Format: format-patch
Series: patch 0002
Subject: WIP: Interface changes for partition_bound_{cmp/bsearch}
File+
src/backend/catalog/partition.c 96 39
From 2830316f6d0f2e74a3e7960290df3a75aad10720 Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Tue, 22 Aug 2017 11:33:27 +0900
Subject: [PATCH 2/4] WIP: 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 ccf8a1fa67..0133748234 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -111,6 +111,30 @@ typedef struct PartitionRangeBound
 	bool		lower;			/* this is the lower (vs upper) bound */
 } PartitionRangeBound;
 
+/*
+ * PartitionBoundCmpArg - Caller-defined argument to be passed to
+ *						  partition_bound_cmp()
+ *
+ * The first (fixed) argument involved in a comparison is the user-defined
+ * partition bound of a given existing partition, 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
+ * (ndatums = number of partition key columns).
+ */
+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,
@@ -139,14 +163,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);
 
@@ -755,10 +780,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;
@@ -809,6 +840,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 &&
@@ -830,8 +862,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)
 					{
@@ -845,9 +880,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)
 							{
 								/*
@@ -2380,12 +2415,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];
 				}
@@ -2397,6 +2435,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
@@ -2427,12 +2466,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
@@ -2629,12 +2669,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;
@@ -2656,11 +2696,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;
@@ -2668,17 +2708,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
@@ -2689,12 +2747,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;
 			}
 
@@ -2708,20 +2767,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,
@@ -2734,8 +2792,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