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

text/plain

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

Patch

Format: format-patch
Series: patch 0003
Subject: WIP: Interface changes for partition_bound_{cmp/bsearch}
File+
src/backend/catalog/partition.c 90 33
From 1921fc38dee9bd89f42f89012dd1d57ead4dc951 Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Tue, 22 Aug 2017 11:33:27 +0900
Subject: [PATCH 3/5] 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 | 123 +++++++++++++++++++++++++++++-----------
 1 file changed, 90 insertions(+), 33 deletions(-)

diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index bb3009e5b3..14876f8ea3 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -105,6 +105,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,
@@ -131,14 +155,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);
 
 /*
  * RelationBuildPartitionDesc
@@ -663,10 +688,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;
@@ -717,6 +748,7 @@ check_new_partition_bound(char *relname, Relation parent,
 					PartitionBoundInfo boundinfo = partdesc->boundinfo;
 					int			offset;
 					bool		equal;
+					PartitionBoundCmpArg	arg;
 
 					Assert(boundinfo && boundinfo->ndatums > 0 &&
 						   boundinfo->strategy == PARTITION_STRATEGY_RANGE);
@@ -736,8 +768,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)
 					{
@@ -751,9 +786,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)
 							{
 								/*
@@ -2037,9 +2072,14 @@ get_partition_for_tuple(PartitionDispatch *pd,
 		{
 			/* Else bsearch in partdesc->boundinfo */
 			bool		equal = false;
+			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);
 			switch (key->strategy)
 			{
 				case PARTITION_STRATEGY_LIST:
@@ -2237,12 +2277,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;
@@ -2264,11 +2304,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;
@@ -2276,17 +2316,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
@@ -2297,12 +2355,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;
 			}
 
@@ -2316,20 +2375,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,
@@ -2342,8 +2400,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